on master help sign in
Merge pull request #4658 from martinbaker/mydoc

add to proof documentation

commit9d03084a33157d441003c08174e9b01961b511bc authorNiklas Larsson <metaniklas@gmail.com> dateThu 21 Mar 2019, 15:09 (8 years ago) parenta5f4d7dc0da8e7
5 files changed+363
CHANGELOG.md+1 CONTRIBUTORS+1 docs/proofs/definitional.rst+231 docs/proofs/index.rst+2 docs/proofs/propositional.rst+128
CHANGELOG.md+1
@@ -1,4 +1,5 @@
11# New in next version
2++ Documentation added to proof section
23
34
45## Library updates
CONTRIBUTORS+1
@@ -143,6 +143,7 @@ Luke Palmer
143143Mark Farrell
144144Markus Klink
145145Markus Pfeiffer
146+Martin Baker
146147Mathnerd314
147148Mattias Lundell
148149Matvey B. Aksenov
docs/proofs/definitional.rstnew file+231
@@ -0,0 +1,231 @@
1+In order to understand how to write proofs in Idris I think its worth clarifying some fundamentals, such as,
2+
3+- Propositions and judgments
4+- Boolean and constructive logic
5+- Curry-Howard correspondence
6+- Definitional and propositional equalities
7+- Axiomatic and constructive approaches
8+
9+Propositions and Judgments
10+==========================
11+
12+Propositions are the subject of our proofs, before the proof then we can't formally say if they are true or not. If the proof is successful then the result is a 'judgment'.
13+For instance, if the ``proposition`` is,
14+
15++-------+
16+| 1+1=2 |
17++-------+
18+
19+When we prove it, the ``judgment`` is,
20+
21++------------+
22+| 1+1=2 true |
23++------------+
24+
25+Or if the ``proposition`` is,
26+
27++-------+
28+| 1+1=3 |
29++-------+
30+
31+Obviously we can't prove it is true, but it is still a valid proposition and perhaps we can prove it is false so the ``judgment`` is,
32+
33++-------------+
34+| 1+1=3 false |
35++-------------+
36+
37+This may seem a bit pedantic but it is important to be careful, in mathematics not every proposition is true or false for instance, a proposition may be unproven or even unprovable.
38+
39+So the logic here is different from the logic that comes from boolean algebra. In that case what is not true is false and what is not false is true. The logic we are using here does not have this 'law of excluded middle' so we have to be careful not to use it.
40+
41+A false proposition is taken to be a contradiction and if we have a contradiction then we can prove anything, so we need to avoid this. Some languages, used in proof assistants, prevent contradictions but such languages cannot be Turing complete, so Idris does not prevent contradictions.
42+
43+The logic we are using is called constructive (or sometimes intuitional) because we are constructing a 'database' of judgments.
44+
45+There are also many other types of logic, another important type of logic for Idris programmers is '``linear logic``' but that's not discussed on this page.
46+
47+Curry-Howard correspondence
48+===========================
49+
50+So how to we relate these proofs to Idris programs? It turns out that there is a correspondence between constructive logic and type theory. They are the same structure and we can switch backward and forward between the two notations because they are the same thing.
51+
52+The way that this works is that a proposition is a type so this,
53+
54+.. code-block:: idris
55+
56+ Idris> 1+1=2
57+ 2 = 2 : Type
58+
59+is a proposition and it is also a type. This is built into Idris so when an '=' equals sign appears in a function type an equality type is generated. The following will also produce an equality type:
60+
61+
62+.. code-block:: idris
63+
64+ Idris> 1+1=3
65+ 2 = 3 : Type
66+
67+Both of these are valid propositions so both are valid equality types. But how do we represent true judgment, that is, how do we denote 1+1=2 is true but not 1+1=3.
68+A type that is true is inhabited, that is, it can be constructed. An equality type has only on constructor 'Refl' so a proof of 1+1=2 is
69+
70+.. code-block:: idris
71+
72+ onePlusOne : 1+1=2
73+ onePlusOne = Refl
74+
75+So how can Refl, which is a constructor without any parameters, construct and equality type? If we type it on its own then it can't:
76+
77+.. code-block:: idris
78+
79+ Idris> Refl
80+ (input):Can't infer argument A to Refl, Can't infer argument x to Refl
81+
82+So it must pattern match on its return type:
83+
84+.. code-block:: idris
85+
86+ Idris> the (1=1) Refl
87+ Refl : 1 = 1
88+
89+So now that we can represent propositions as types other aspects of propositional logic can also be translated to types as follows:
90+
91++----------+-------------------+--------------------------+
92+| | propositions | example of possible type |
93++----------+-------------------+--------------------------+
94+| A | x=y | |
95++----------+-------------------+--------------------------+
96+| B | y=z | |
97++----------+-------------------+--------------------------+
98+| and | A /\ B | Pair(x=y,y=z) |
99++----------+-------------------+--------------------------+
100+| or | A \/ B | Either(x=y,y=z) |
101++----------+-------------------+--------------------------+
102+| implies | A -> B | (x=y) -> (y=x) |
103++----------+-------------------+--------------------------+
104+| for all | y=z | |
105++----------+-------------------+--------------------------+
106+| exists | y=z | |
107++----------+-------------------+--------------------------+
108+
109+
110+And (conjunction)
111+-----------------
112+
113+We can have a type which corresponds to conjunction:
114+
115+.. code-block:: idris
116+
117+ AndIntro : a -> b -> A a b
118+
119+There is a built in type called 'Pair'.
120+
121+Or (disjunction)
122+----------------
123+
124+We can have a type which corresponds to disjunction:
125+
126+.. code-block:: idris
127+
128+ data Or : Type -&gt; Type -&gt; Type where
129+ OrIntroLeft : a -&gt; A a b
130+ OrIntroRight : b -&gt; A a b
131+
132+There is a built in type called 'Either'.
133+
134+Definitional and Propositional Equalities
135+=========================================
136+
137+We have seen that we can 'prove' a type by finding a way to construct a term. In the case of equality types there is only one constructor which is 'Refl'.
138+We have also seen that each side of the equation does not have to be identical like '2=2'. It is enough that both sides are ``definitionaly equal`` like this:
139+
140+.. code-block:: idris
141+
142+ onePlusOne : 1+1=2
143+ onePlusOne = Refl
144+
145+So both sides of this equation nomalise to 2 and so Refl will type match and the proposition is proved.
146+
147+We don't have to stick to terms, can also use symbolic parameters so the following will compile:
148+
149+.. code-block:: idris
150+
151+ varIdentity : m = m
152+ varIdentity = Refl
153+
154+If a proposition/equality type is not definitionaly equal but is still true then it is ``propositionaly equal``. In this case we may still be able to prove it but some steps in the proof may require us to add something into the terms or at least to take some sideways steps to get to a proof.
155+
156+Especially when working with equalities containing variable terms (inside functions) it can be hard to know which equality types are definitially equal, in this example plusReducesL is '``definitially equal``' but plusReducesR is not (although it is '``propositionaly equal``'). The only difference between them is the order of the operands.
157+
158+.. code-block:: idris
159+
160+ plusReducesL : (n:Nat) -&gt; plus Z n = n
161+ plusReducesL n = Refl
162+
163+ plusReducesR : (n:Nat) -&gt; plus n Z = n
164+ plusReducesR n = Refl
165+
166+plusReducesR gives the following error:
167+
168+
169+.. code-block:: idris
170+
171+ - + Errors (1)
172+ `-- proof.idr line 6 col 17:
173+ When checking right hand side of plusReducesR with expected type
174+ plus n 0 = n
175+
176+ Type mismatch between
177+ n = n (Type of Refl)
178+ and
179+ plus n 0 = n (Expected type)
180+
181+ Specifically:
182+ Type mismatch between
183+ n
184+ and
185+ plus n 0
186+
187+So why is 'Refl' able to prove some equality types but not others?
188+
189+The first answer is that 'plus' is defined in such a way that it splits on its first argument so it is simple to prove when 0 is the first argument but not the second. So what is the general way to know if Refl will work?
190+
191+If an equality type can be proved/constructed by using Refl alone it is known as a ``definitional equality``. In order to be definitinally equal both sides of the equation must normalise to unique values. That is, each step in the proof must reduce the term so each step is effectively forced.
192+
193+So when we type 1+1 in Idris it is immediately converted to 2 because definitional equality is built in.
194+
195+.. code-block:: idris
196+
197+ Idris> 1+1
198+ 2 : Integer
199+
200+In the following pages we discuss how to resolve propositionaly equalies.
201+
202+Axiomatic and Constructive Approaches
203+=====================================
204+
205+How should we define types so that we can do proofs on them? In the natural numbers with plus example we could have started by treating it as a group based on the plus operator. So we have axioms:
206+
207+- for all x,y : ``x+y=y+x``
208+- for all x: ``x + 0 = x = 0 + x``
209+- for all x,y,z: ``(x + y) + z = x + (x + z)``
210+
211+Then we can implement '+' so that it respects these axioms (presumably implemented in hardware).
212+
213+These are axioms, that is a propositions/types that are asserted to be true without proof. In Idris we can use the 'postulate' keyword
214+
215+
216+.. code-block:: idris
217+
218+ commutePlus ``postulate``: x -> y -> plus x y = plus y x
219+
220+Alternatively we could define the natural numbers based on Zero and Successor. The axioms above then become derived rules and we also gain the ability to do inductive proofs.
221+
222+As we know, Idris uses both of these approaches with automatic coercion between them which gives the best of both worlds.
223+
224+So what can we learn from this to implement out own types:
225+
226+- Should we try to implement both approaches?
227+- Should we define our types by constructing up from primitive types?
228+
229+Proof theory affects these design decisions.
230+
231+
docs/proofs/index.rst+2
@@ -18,8 +18,10 @@ A tutorial on theorem proving in Idris.
1818.. toctree::
1919 :maxdepth: 1
2020
21+ definitional
2122 pluscomm
2223 inductive
2324 patterns
25+ propositional
2426 interactive
2527
docs/proofs/propositional.rstnew file+128
@@ -0,0 +1,128 @@
1+This page attempts to explain some of the techniques used in Idris to prove propositional equalities.
2+
3+Proving Propositional Equality
4+==============================
5+
6+We have seen that definitional equalities can be proved using Refl since they always normalise to unique values that can be compared directly.
7+
8+However with propositional equalities we are using symbolic variables they do not always normalse.
9+
10+So to take the previous example:
11+
12+plusReducesR : (n:Nat) -> plus n Z = n
13+
14+In this case 'plus n Z' does not normalise to n. Even though both sides are equal we cannot pattern match Refl.
15+
16+If the pattern match cannot match for all 'n' then the way around this is to separately match all possible values of 'n'. In the case of natural numbers we do this by induction.
17+
18+So here:
19+
20+.. code-block:: idris
21+
22+ plusReducesR : n = plus n 0
23+ plusReducesR {n = Z} = Refl
24+ plusReducesR {n = (S k)} = let rec = plus_commutes_Z {n=k} in
25+ rewrite rec in Refl
26+
27+we don't call Refl to match on 'n = plus n 0' forall 'n' we call it for every number separately. So, in the second line, the pattern matcher knows to substitute Z for n in the type being matched. This uses 'rewrite' which is explained below.
28+
29+Replace
30+=======
31+
32+This implements the 'indiscernability of identicals' principle, if two terms are equal then they have the same properties. In other words, if x=y, then we can substitute y for x in any expression. In our proofs we can express this as:
33+
34+ if x=y
35+ then P x = P y
36+
37+where P is a pure function representing the property. In the examples below P is an expression in some variable with a type like this: P: n -> Type
38+
39+So if n is a natural number variable then P could be something like 2*n + 3.
40+
41+To use this in our proofs there is the following function in the prelude:
42+
43+.. code-block:: idris
44+
45+ ||| Perform substitution in a term according to some equality.
46+ replace : {a:_} -> {x:_} -> {y:_} -> {P : a -> Type} -> x = y -> P x -> P y
47+ replace Refl prf = prf
48+
49+Removing the implicits, if we supply an equality (x=y) and a proof of a property of x (P x) then we get a proof of a property of y (P y)
50+
51+.. code-block:: idris
52+
53+ > :t replace
54+ replace : (x = y) -> P x -> P y
55+
56+So, in the following example, if we supply p1 x which is a proof that x=2 and the equality x=y then we get a proof that y=2.
57+
58+.. code-block:: idris
59+
60+ p1: Nat -> Type
61+ p1 n = (n=2)
62+
63+ testReplace: (x=y) -> (p1 x) -> (p1 y)
64+ testReplace a b = replace a b
65+
66+Rewrite
67+=======
68+
69+Similar to 'replace' above but Idris provides a nicer syntax which makes 'rewrite' easier to use in examples like plusReducesR above.
70+
71+.. code-block:: idris
72+
73+ rewrite__impl : (P : a -> Type) -> x = y -> P y -> P x
74+ rewrite__impl p Refl prf = prf
75+
76+The difference from 'replace' above is nicer syntax and the property p1 is explicitly supplied and it goes in the opposite direction (input and output reversed).
77+
78+Example: again we supply p1 which is a proof that x=2 and the equality x=y then we get a proof that y=2.
79+
80+.. code-block:: idris
81+
82+ p1: Nat -> Type
83+ p1 x = (x=2)
84+
85+ testRewrite2: (x=y) -> (p1 y) -> (p1 x)
86+ testRewrite2 a b = rewrite a in b
87+
88+We can think of rewrite doing this:
89+
90+ * Start with a equation x=y and a property P: x -> Type
91+ * Searches y in P
92+ * Replaces all occurrences of y with x in P.
93+
94+That is, we are doing a substitution.
95+
96+Symmetry and Transitivity
97+=========================
98+
99+In addition to 'reflexivity' equality also obeys 'symmetry' and 'transitivity' and these are also included in the prelude:
100+
101+.. code-block:: idris
102+
103+ ||| Symmetry of propositional equality
104+ sym : {left:a} -> {right:b} -> left = right -> right = left
105+ sym Refl = Refl
106+
107+ ||| Transitivity of propositional equality
108+ trans : {a:x} -> {b:y} -> {c:z} -> a = b -> b = c -> a = c
109+ trans Refl Refl = Refl
110+
111+Heterogeneous Equality
112+======================
113+
114+Also included in the prelude:
115+
116+.. code-block:: idris
117+
118+ ||| Explicit heterogeneous ("John Major") equality. Use this when Idris
119+ ||| incorrectly chooses homogeneous equality for `(=)`.
120+ ||| @ a the type of the left side
121+ ||| @ b the type of the right side
122+ ||| @ x the left side
123+ ||| @ y the right side
124+ (~=~) : (x : a) -> (y : b) -> Type
125+ (~=~) x y = (x = y)
126+
127+
128+