AbstractDataType - Nat - abstract-data-type

I got this abstract model here and try to understand how it works but can't figure it out.
type: NAT
constructor
null: → NAT
succ: NAT → NAT
operator
add: NAT×NAT→ NAT
axiom x,y : NAT
add(X, null) = X
add(X, succ(Y)) = succ(add(X, Y))
The problem is with the add. I tried to put some numbers in but ... how does it work? -
add(2, succ(3)) = succ(add(2, 3)) ... and now? I just want 2+3 = 5

NAT is the set of natural numbers together with '+' and succ is the successor function (often seen in relation with the Peano axioms)
Your example for 2+3 calculates like this:
add(2,3) = succ(add(2,2))
= succ(succ(add(2,1)))
= succ(succ(succ(add(2,0))))
= succ(succ(succ(2)))
= succ(succ(3))
= succ(4)
= 5

Related

Difference between parameters and members of a class

I am new to Coq and was wondering what is the difference between the following things:
Class test (f g: nat -> nat) := {
init: f 0 = 0 /\ g 0 = 0;
output: ...another proposition about f and g...;
}.
and
Class test := {
f: nat -> nat;
g: nat -> nat;
init: f 0 = 0 /\ g 0 = 0;
output: ...another proposition about f and g...;
}.
Could anyone provide an explanation ?
The difference between them is referred to as bundling.
Class test (f g: nat -> nat) := {
init: f 0 = 0 /\ g 0 = 0;
output: ...another proposition about f and g...;
}.
is unbundled, and
Class test := {
f: nat -> nat;
g: nat -> nat;
init: f 0 = 0 /\ g 0 = 0;
output: ...another proposition about f and g...;
}.
is bundled.
The advantage of bundling is that you don't need to always provide f and g. The advantage of unbundling is that you can have different instances of the same class sharing the same f and g. If you bundle them, Coq will not be easily convinced that different instances share parameters.
You can read more about this in Type Classes for Mathematics in Type Theory.
To complement Ana’s excellent answer, here is a practical difference:
the unbundled version (call it utest) allows you to write the logical statement utest f g about a specific pair of functions f and g,
whereas the bundled version (call it btest) allows you to state that there exists a pair of functions which satisfies the properties; you can later refer to these functions by the projection names f and g.
So, roughly speaking:
btest is “equivalent” to ∃ f g, utest f g;
utest f' g' is “equivalent” to btest ∧ “the f (resp. g) in the aforementioned proof of btest is equal to f' (resp. g')”.
More formally, here are the equivalences for a minimal example
(in this code, the notation { x : A | B } is a dependent pair type,
i.e. the type of (x, y) where x : A and y : B
and the type B depends on the value x):
(* unbundled: *)
Class utest (x : nat) : Prop := {
uprop : x = 0;
}.
(* bundled: *)
Class btest : Type := {
bx : nat;
bprop : bx = 0;
}.
(* [btest] is equivalent to: *)
Goal { x : nat | utest x } -> btest.
Proof.
intros [x u]. econstructor. exact (#uprop x u).
Qed.
Goal btest -> { x : nat | utest x }.
Proof.
intros b. exists (#bx b). constructor. exact (#bprop b).
Qed.
(* [utest x] is equivalent to: *)
Goal forall x, { b : btest | #bx b = x } -> utest x.
Proof.
intros x [b <-]. constructor. exact (#bprop b).
Qed.
Goal forall x, utest x -> { b : btest | #bx b = x }.
Proof.
intros x u. exists {| bx := x ; bprop := #uprop x u |}. reflexivity.
Qed.
(* NOTE: Here I’ve explicited all implicit arguments; in fact, you
can let Coq infer them, and write just [bx], [bprop], [uprop]
instead of [#bx b], [#bprop b], [#uprop x u]. *)
In this example, we can also observe a difference with respect to computational relevance: utest can live in Prop, because its only member, uprop, is a proposition. On the other hand, I cannot really put btest in Prop, because that would mean that both bx and bprop would live in Prop but bf is computationally relevant. In other words, Coq gives you this warning:
Class btest : Prop := {
bx : nat;
bprop : bx = 0;
}.
(* WARNING:
bx cannot be defined because it is informative and btest is not.
bprop cannot be defined because the projection bx was not defined.
*)

How can I reference an Idris interface method from within the same interface declaration?

I built a little TotalOrder class that has stronger proof properties than the regular Ord class. The problem is that these properties need to refer to each other in ways I'm not sure how to do, syntactically.
I need to reference my lessThan type in the other methods in the interface, but it seems to be getting treated as a regular (implicitly forall'd) variable.
module Order
%default total
public export
data Ordering : (t -> t -> Type) -> t -> t -> Type where
LessThan : f x y -> Ordering f x y
Equal : x = y -> Ordering f x y
GreaterThan : f y x -> Ordering f x y
public export
interface TotalOrder a where
lessThan : a -> a -> Type
compare : (x, y : a) -> Ordering lessThan x y
ltNeq : lessThan x y -> x = y -> Void
ltNgt : lessThan x y -> lessThan y x -> Void
-- Implementation for Nats
compareNat : (x, y : Nat) -> Ordering LT x y
compareNat x y = ...
ltNeqNat : LT x y -> x = y -> Void
ltNeqNat lt eq = ...
ltNgtNat : LT x y -> LT y x -> Void
ltNgtNat lt gt = ...
implementation TotalOrder Nat where
lessThan = LT
compare = compareNat -- THIS LINE REFUSES TO COMPILE
ltNeq = ltNeqNat
ltNgt = ltNgtNat
As best I can determine, the typechecker automatically assumes that the lessThans in function position in ltNeq and ltNgt are the same as the lessThan declared in the interface, but the lessThan in argument position in compare is treated as a regular argument to compare, meaning that the type for the Nat implementation is
compare : {lessThan : Nat -> Nat -> Type} -> (x, y : Nat) -> Ordering lessThan x y
rather than
compare : (x, y : Nat) -> Ordering LT x y
and compare = compareNat no longer typechecks. When I run into this problem in top-level functions, fully-qualifying the name works, but I'm not sure what the fully-qualified name here would be, and the obvious ideas (Order.lessThan, TotalOrder.lessThan, Order.TotalOrder.lessThan) all get "no such variable"d.

Is there a way to prove stuff in Idris without a model?

I have been trying to implement the Incidence Axioms in geometry for Hilbert plane. And came up with the following axioms:
interface (Eq point) => Plane line point where
-- Abstract notion for saying three points lie on the same line.
colinear : point -> point -> point -> Bool
coplanar : point -> point -> point -> Bool
contains : line -> point -> Bool
-- Intersection between two lines
intersects_at : line -> line -> point -> Bool
intersection_def : (contains l a = True) -> (contains m a = True) -> (intersects_at l m a = True)
-- For any two distinct points there is a line that contains them.
line_contains_two_points : (a,b : point) -> (a /= b) = True -> (l : line ** (contains l a = True, contains l b = True ))
-- If two points are contained by l and m then l = m
two_pts_define_line : contains l a = True -> contains l b = True -> contains m a = True -> contains m b = True -> l = m
-- There exists 3 non-colinear points.
three_non_colinear_pts : (a : point ** b : point ** c : point ** (colinear a b c = False, (a /= b) = True, (b /= c) = True, (a /= c) = True))
-- Any lines contains at least two points.
contain_two_pts : (l : line) -> (a : point ** b : point ** (contains l a = True, contains l b = True))
I want to show that a line intersects with another line at most once. So I came up with the following statement:
intersect_at_most_one_point : (l, m : line) -> (a : point) -> (intersects_at l m a = True) -> (intersects_at l m b = True) -> a = b
Which reads:
Given two lines, if they intersect at two points a and b then it must be that a = b.
However I get the error:
When checking type of Main.intersect_at_most_one_point:
When checking argument x to type constructor =:
Can't find implementation for Plane line point
So what I suspect this means is that it wants some sort of data value that I can show satisfies the idea of an incidence geometry. I interpret this mathematically as I need a model for the system. The problem is there are a lot of of "geometries" which satisfy these axioms that are vastly different.
Is it possible to derive theorems about an interface without the need for any any explicit data to work with?
You need to add the Plane constraint to your type signature of intersect_at_most_one_point:
intersect_at_most_one_point : Plane line point =>
(l, m : line) -> (a : point) ->
(intersects_at l m a = True) -> (intersects_at l m b = True) ->
a = b

Why are these two tuples in idris equal?

I am reading Type driven development with Idris, and one of the exercises asks the reader to define a type TupleVect, such that a vector can be represented as:
TupleVect 2 ty = (ty, (ty, ()))
I solved it by defining the following type:
TupleVect : Nat -> Type -> Type
TupleVect Z ty = ()
TupleVect (S k) ty = (ty, TupleVect k ty)
The following test typechecks:
test : TupleVect 4 Nat
test = (1,2,3,4,())
My question is, why is (1,2,3,4,()) == (1,(2,(3,(4,()))))? I would have thought that the right hand side is a 2-tuple, consisting of an Int and another tuple.
Checking the documentation at http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#tuples, you can see that tuples are represented as nested pairs.
Hence (x, y, z) == (x, (y, z)) for every x, y, z

Helper Function to Determine if Nat `mod` 5 == 0

Xash provided me with a helpful answer on Function to Determine if Nat is Divisible by 5 at Compile-Time (that I re-named from my original long name):
onlyModBy5 : (n : Nat) -> n `modNat` 5 = 0 -> Nat
onlyModBy5 n prf = n
A previous answer educated me how to run it on the REPL using the Refl argument:
-- 5 % 5 == 0, so it should compile
*Test> onlyModBy5 5 Refl
5 : Nat
-- 7 % 5 == 2, so it should not compile
*Test> onlyModBy5 7 Refl
(input):1:12:When checking an application of function Main.onlyModBy5:
Type mismatch between
x = x (Type of Refl)
and
modNat 7 5 = 0 (Expected type)
Specifically:
Type mismatch between
2
and
0
Then, I tried to define a helper function that would provide the second prf (proof) argument for conciseness. In other words, I'd prefer the caller of this function to not have to provide the Refl argument.
onlyModBy5Short : (n : Nat) -> Nat
onlyModBy5Short n = onlyModBy5 n Refl
But, it does not compile:
When checking right hand side of onlyModBy5Short with expected type
Nat
When checking an application of function Main.onlyModBy5:
Type mismatch between
0 = 0 (Type of Refl)
and
modNat n 5 = 0 (Expected type)
Specifically:
Type mismatch between
0
and
Prelude.Nat.modNatNZ, mod' n 4 SIsNotZ n n 4
Holes: Main.onlyModBy5Short
How, if possible, can this function be written?
You can make onlyModBy5's second argument an auto argument:
onlyModBy5 : (n : Nat) -> {auto prf : n `modNat` 5 = 0} -> Nat
onlyModBy5 n = n
This works because for a given literal value of n, n `modNat` 5 can always be reduced, and so n `modNat` 5 = 0 will always reduce to 0 = 0 (in which case the constructor Refl has the right type) unless n is truly not divisible by 5.
Indeed, this will allow you to typecheck
foo : Nat
foo = onlyModBy5 25
but reject
bar : Nat
bar = onlyModBy5 4