X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=weblib%2Ftutorial%2Fchapter2.ma;h=6784de617d3c5462cbba74856bc80079ed70e974;hb=ccf5878f2a2ec7f952f140e162391708a740517b;hp=42b3d8e74043eed56c8c5625cfad6cfab1143b38;hpb=634dd58a077d3380f90e47a5f6a40a648ad9f17b;p=helm.git diff --git a/weblib/tutorial/chapter2.ma b/weblib/tutorial/chapter2.ma index 42b3d8e74..6784de617 100644 --- a/weblib/tutorial/chapter2.ma +++ b/weblib/tutorial/chapter2.ma @@ -1,3 +1,6 @@ +(* +h1 class="section"Induction and Recursion/h1 +*) include "basics/types.ma". (* Most of the types we have seen so far are enumerated types, composed by a @@ -9,7 +12,7 @@ is provided by the natural numbers, that can be defined as the smallest set generated by a constant 0 and a successor function from natural numbers to natural numbers *) -inductive nat : Type[0] ≝ +img class="anchor" src="icons/tick.png" id="nat"inductive nat : Type[0] ≝ | O :nat | S: nat →nat. @@ -23,13 +26,15 @@ allowed to make recursive calls on structurally smaller arguments than the ones you received in input. Most mathematical functions can be naturally defined in this way. For instance, the sum of two natural numbers can be defined as follows *) -let rec add n m ≝ +img class="anchor" src="icons/tick.png" id="add"let rec add n m ≝ match n with [ O ⇒ m | S a ⇒ a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (add a m) ]. -(* It is worth to observe that the previous algorithm works by recursion over the +(* +h2 class="section"Elimination/h2 +It is worth to observe that the previous algorithm works by recursion over the first argument. This means that, for instance, (add O x) will reduce to x, as expected, but (add x O) is stuck. How can we prove that, for a generic x, (add x O) = x? The mathematical tool to do @@ -44,7 +49,7 @@ will break down your task to prove the two subgoals P(0) and ∀m.P(m) → P(S m Let us apply it to our case *) -lemma add_0: ∀a. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a. +img class="anchor" src="icons/tick.png" id="add_0"lemma add_0: ∀a. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a. #a elim a (* If you stop the computation here, you will see on the right the two subgoals @@ -58,7 +63,7 @@ normalize // qed. (* In a similar way, it is convenient to state a lemma about the behaviour of add when the second argument is not zero. *) -lemma add_S : ∀a,b. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a b) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a b). +img class="anchor" src="icons/tick.png" id="add_S"lemma add_S : ∀a,b. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a b) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a b). (* In the same way as before, we proceed by induction over a. *) @@ -67,7 +72,7 @@ qed. (* We are now in the position to prove the commutativity of the sum *) -theorem add_comm : ∀a,b. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a b a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a b a. +img class="anchor" src="icons/tick.png" id="add_comm"theorem add_comm : ∀a,b. a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a a b a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a b a. #a elim a normalize (* We have two sub goals: @@ -81,11 +86,11 @@ For Matita, the task is trivial and we can simply close the goal with // *) (* COERCIONS *) -inductive bool : Type[0] ≝ +img class="anchor" src="icons/tick.png" id="bool"inductive bool : Type[0] ≝ | tt : bool | ff : bool. -definition nat_of_bool ≝ λb. match b with +img class="anchor" src="icons/tick.png" id="nat_of_bool"definition nat_of_bool ≝ λb. match b with [ tt ⇒ a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a | ff ⇒ a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a ]. @@ -94,14 +99,16 @@ definition nat_of_bool ≝ λb. match b with (* Let us now define the following function: *) -definition twice ≝ λn.a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a n n. +img class="anchor" src="icons/tick.png" id="twice"definition twice ≝ λn.a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a n n. -(* We are interested to prove that for any natural number n there exists a natural +(* +h2 class="section"Existential/h2 +We are interested to prove that for any natural number n there exists a natural number m that is the integer half of n. This will give us the opportunity to introduce new connectives and quantifiers and, later on, to make some interesting consideration on proofs and computations. *) -theorem ex_half: ∀n.a title="exists" href="cic:/fakeuri.def(1)"∃/am. n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a m a title="logical or" href="cic:/fakeuri.def(1)"∨/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a m). +img class="anchor" src="icons/tick.png" id="ex_half"theorem ex_half: ∀n.a title="exists" href="cic:/fakeuri.def(1)"∃/am. n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a m a title="logical or" href="cic:/fakeuri.def(1)"∨/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a m). #n elim n normalize (* We proceed by induction on n, that breaks down to the following goals: @@ -120,17 +127,19 @@ also automatically close G1. *) [@(a href="cic:/matita/basics/logic/ex.con(0,1,2)"ex_intro/a … a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a) %1 // -(* The case of G2 is more complex. We should start introducing x and the +(* +h2 class="section"Destructuration/h2 +The case of G2 is more complex. We should start introducing x and the inductive hypothesis IH: ∃m. x = add m m ∨ x = S (add m m) At this point we should assume the existence of m enjoying the inductive -hypothesis. To eliminate the existential from the context we can just use the case -tactic. This situation where we introduce something into the context and immediately -eliminate it by case analysis is so frequent that Matita provides a convenient -shorthand: you can just type a single "*". -The star symbol should be reminiscent of an explosion: the idea is that you have a -structured hypothesis, and you ask to explode it into its constituents. In the case -of the existential, it allows to pass from a goal of the shape +hypothesis. To eliminate the existential from the context we can just use the +case tactic. This situation where we introduce something into the context and +immediately eliminate it by case analysis is so frequent that Matita provides a +convenient shorthand: you can just type a single "*". +The star symbol should be reminiscent of an explosion: the idea is that you have +a structured hypothesis, and you ask to explode it into its constituents. In the +case of the existential, it allows to pass from a goal of the shape (∃x.P x) → Q to a goal of the shape ∀x.P x → Q @@ -138,132 +147,141 @@ to a goal of the shape |#x * (* At this point we are left with a new goal with the following shape G3: ∀m. x = add m m ∨ x = S (add m m) → .... -We should introduce m, the hypothesis H: x = add m m ∨ x = S (add m m), and then -reason by cases on this hypothesis. It is the same situation as before: we explode the -disjunctive hypothesis into its possible consituents. In the case of a disjunction, the -* tactic allows to pass from a goal of the form +We should introduce m, the hypothesis H: x = add m m ∨ x = S (add m m), and +then reason by cases on this hypothesis. It is the same situation as before: +we explode the disjunctive hypothesis into its possible consituents. In the case +of a disjunction, the * tactic allows to pass from a goal of the form A∨B → Q to two subgoals of the form A → Q and B → Q *) #m * #eqx -(* In the first subgoal, we are under the assumption that x = add m m. The half of (S x) -is hence m, and we have to prove the right branch of the disjunction. -In the second subgoal, we are under the assumption that x = S (add m m). The halh of (S x) -is hence (S m), and have to follow the left branch of the disjunction. +(* In the first subgoal, we are under the assumption that x = add m m. The half +of (S x) is hence m, and we have to prove the right branch of the disjunction. +In the second subgoal, we are under the assumption that x = S (add m m). The halh +of (S x) is hence (S m), and have to follow the left branch of the disjunction. *) [@(a href="cic:/matita/basics/logic/ex.con(0,1,2)"ex_intro/a … m) /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/basics/logic/Or.con(0,2,2)"or_intror/a/span/span/ | @(a href="cic:/matita/basics/logic/ex.con(0,1,2)"ex_intro/a … (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a m)) normalize /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/basics/logic/Or.con(0,1,2)"or_introl/a/span/span/ ] qed. -(* Instead of proving the existence of a number corresponding to the half of n, we could -be interested in computing it. The best way to do it is to define this division operation -together with the remainder, that in our case is just a boolean value: tt if the input term -is even, and ff if the input term is odd. Since we must return a pair, we could use a -suitably defined record type, or simply a product type nat × bool, defined in the basic library. -The product type is just a sort of general purpose record, with standard fields fst and snd, -called projections. A pair of values n and m is written (pair … m n) or \langle n,m \rangle - -visually rendered as 〈n,m〉 +(* +h2 class="section"Computing vs. Proving/h2 +Instead of proving the existence of a number corresponding to the half of n, +we could be interested in computing it. The best way to do it is to define this +division operation together with the remainder, that in our case is just a +boolean value: tt if the input term is even, and ff if the input term is odd. +Since we must return a pair, we could use a suitably defined record type, or +simply a product type nat × bool, defined in the basic library. The product type +is just a sort of general purpose record, with standard fields fst and snd, called +projections. +A pair of values n and m is written (pair … m n) or \langle n,m \rangle - visually +rendered as 〈n,m〉 We first write down the function, and then discuss it.*) -let rec div2 n ≝ +img class="anchor" src="icons/tick.png" id="div2"let rec div2 n ≝ match n with -[ O ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉 +[ O ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/aspan class="error" title="Parse error: [sym,] expected after [term level 19] (in [term])"/span,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a | S a ⇒ span style="text-decoration: underline;"/span let p ≝ (div2 a) in - match (a href="cic:/matita/basics/types/snd.def(1)"snd/a … p) with - [ tt ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/basics/types/fst.def(1)"fst/a … p),a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉 - | ff ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.def(1)"fst/a … p, a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/a〉 + match (a href="cic:/matita/basics/types/snd.fix(0,2,1)"snd/aspan class="error" title="Parse error: SYMBOL ':' or RPAREN expected after [term] (in [term])"/span … p) with + [ tt ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p),a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a + | ff ⇒ a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p, a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a ] ]. -(* The function is computed by recursion over the input n. If n is 0, then the quotient -is 0 and the remainder is tt. If n = S a, we start computing the half of a, say 〈q,b〉. -Then we have two cases according to the possible values of b: if b is tt, then we must return - 〈q,ff〉, while if b = ff then we must return 〈S q,tt〉. - -It is important to point out the deep, substantial analogy between the algorithm for -computing div2 and the the proof of ex_half. In particular ex_half returns a -proof of the kind ∃n.A(n)∨B(n): the really informative content in it is the witness -n and a boolean indicating which one between the two conditions A(n) and B(n) is met. -This is precisely the quotient-remainder pair returned by div2. -In both cases we proceed by recurrence (respectively, induction or recursion) over the -input argument n. In case n = 0, we conclude the proof in ex_half by providing the -witness O and a proof of A(O); this corresponds to returning the pair 〈O,ff〉 in div2. -Similarly, in the inductive case n = S a, we must exploit the inductive hypothesis -for a (i.e. the result of the recursive call), distinguishing two subcases according -to the the two possibilites A(a) or B(a) (i.e. the two possibile values of the remainder -for a). The reader is strongly invited to check all remaining details. +(* The function is computed by recursion over the input n. If n is 0, then the +quotient is 0 and the remainder is tt. If n = S a, we start computing the half +of a, say 〈q,b〉. Then we have two cases according to the possible values of b: +if b is tt, then we must return 〈q,ff〉, while if b = ff then we must return +〈S q,tt〉. + +It is important to point out the deep, substantial analogy between the algorithm +for computing div2 and the the proof of ex_half. In particular ex_half returns a +proof of the kind ∃n.A(n)∨B(n): the really informative content in it is the +witness n and a boolean indicating which one between the two conditions A(n) and +B(n) is met. This is precisely the quotient-remainder pair returned by div2. +In both cases we proceed by recurrence (respectively, induction or recursion) over +the input argument n. In case n = 0, we conclude the proof in ex_half by providing +the witness O and a proof of A(O); this corresponds to returning the pair 〈O,ff〉 in +div2. Similarly, in the inductive case n = S a, we must exploit the inductive +hypothesis for a (i.e. the result of the recursive call), distinguishing two subcases +according to the the two possibilites A(a) or B(a) (i.e. the two possibile values of +the remainder for a). The reader is strongly invited to check all remaining details. Let us now prove that our div2 function has the expected behaviour. *) -lemma surjective_pairing: ∀A,B.∀p:Aa title="Product" href="cic:/fakeuri.def(1)"×/aB. p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.def(1)"fst/a … p,a title="pair pi2" href="cic:/fakeuri.def(1)"\snd/a … p〉. +img class="anchor" src="icons/tick.png" id="surjective_pairing"lemma surjective_pairing: ∀A,B.∀p:Aa title="Product" href="cic:/fakeuri.def(1)"×/aB. p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p,a title="pair pi2" href="cic:/fakeuri.def(1)"\snd/aspan class="error" title="Parse error: [sym〉] or [sym,] expected after [term level 19] (in [term])"/span … pa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a. #A #B * // qed. -lemma div2SO: ∀n,q. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉 → a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a n) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aspan style="text-decoration: underline;"/spanq,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/a〉. +img class="anchor" src="icons/tick.png" id="div2SO"lemma div2SO: ∀n,q. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a → a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a n) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aspan style="text-decoration: underline;"/spanq,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a. #n #q #H normalize >H normalize // qed. -lemma div2S1: ∀n,q. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/a〉 → a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a n) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a q,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉. +img class="anchor" src="icons/tick.png" id="div2S1"lemma div2S1: ∀n,q. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a → a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a n) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/aspan class="error" title="Parse error: [term] expected after [sym=] (in [term])"/span a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a q,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a. #n #q #H normalize >H normalize // qed. -lemma div2_ok: ∀n,q,r. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,r〉 → n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a q) (a href="cic:/matita/tutorial/chapter2/nat_of_bool.def(1)"nat_of_bool/a r). +img class="anchor" src="icons/tick.png" id="div2_ok"lemma div2_ok: ∀n,q,r. a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,ra title="Pair construction" href="cic:/fakeuri.def(1)"〉/a → n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a q) (a href="cic:/matita/tutorial/chapter2/nat_of_bool.def(1)"nat_of_bool/a r). #n elim n [#q #r normalize #H destruct // |#a #Hind #q #r - cut (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.def(1)"fst/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a), a href="cic:/matita/basics/types/snd.def(1)"snd/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a)〉) [//] - cases (a href="cic:/matita/basics/types/snd.def(1)"snd/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a)) - [#H >(a href="cic:/matita/tutorial/chapter2/div2S1.def(3)"div2S1/a … H) #H1 destruct @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a span style="text-decoration: underline;">/spana href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a <a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @(Hind … H) + cut (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a), a href="cic:/matita/basics/types/snd.fix(0,2,1)"snd/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a)a title="Pair construction" href="cic:/fakeuri.def(1)"〉/a) [//] + cases (a href="cic:/matita/basics/types/snd.fix(0,2,1)"snd/a … (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a a)) + [#H >(a href="cic:/matita/tutorial/chapter2/div2S1.def(3)"div2S1/a … H) #H1 destruct @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a span style="text-decoration: underline;">/spana href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a whd in ⊢ (???%); <a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @(Hind … H) |#H >(a href="cic:/matita/tutorial/chapter2/div2SO.def(3)"div2SO/a … H) #H1 destruct >a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a @(Hind … H) ] qed. -(* There is still another possibility, however, namely to mix the program and its -specification into a single entity. The idea is to refine the output type of the div2 -function: it should not be just a generic pair 〈q,r〉 of natural numbers but a specific -pair satisfying the specification of the function. In other words, we need the -possibility to define, for a type A and a property P over A, the subset type -{a:A|P(a)} of all elements a of type A that satisfy the property P. Subset types are -just a particular case of the so called dependent types, that is types that can -depend over arguments (such as arrays of a specified length, taken as a parameter). -These kind of types are quite unusual in traditional programming languages, and their -study is one of the new frontiers of the current research on type systems. - -There is nothing special in a subset type {a:A|P(a)}: it is just a record composed by -an element of a of type A and a proof of P(a). The crucial point is to have a language -reach enough to comprise proofs among its expressions. +(* +h2 class="section"Mixing proofs and computations/h2 +There is still another possibility, however, namely to mix the program and its +specification into a single entity. The idea is to refine the output type of the +div2 function: it should not be just a generic pair 〈q,r〉 of natural numbers but a +specific pair satisfying the specification of the function. In other words, we need +the possibility to define, for a type A and a property P over A, the subset type +{a:A|P(a)} of all elements a of type A that satisfy the property P. Subset types +are just a particular case of the so called dependent types, that is types that +can depend over arguments (such as arrays of a specified length, taken as a +parameter).These kind of types are quite unusual in traditional programming +languages, and their study is one of the new frontiers of the current research on +type systems. + +There is nothing special in a subset type {a:A|P(a)}: it is just a record composed +by an element of a of type A and a proof of P(a). The crucial point is to have a +language reach enough to comprise proofs among its expressions. *) -record Sub (A:Type[0]) (P:A → Prop) : Type[0] ≝ +img class="anchor" src="icons/tick.png" id="Sub"record Sub (A:Type[0]) (P:A → Prop) : Type[0] ≝ {witness: A; proof: P witness}. -definition qr_spec ≝ λn.λp.∀q,r. p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,r〉 → n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a q) (a href="cic:/matita/tutorial/chapter2/nat_of_bool.def(1)"nat_of_bool/a r). +img class="anchor" src="icons/tick.png" id="qr_spec"definition qr_spec ≝ λn.λp.∀q,r. p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aq,ra title="Pair construction" href="cic:/fakeuri.def(1)"〉/a → n a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"add/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a q) (a href="cic:/matita/tutorial/chapter2/nat_of_bool.def(1)"nat_of_bool/a r). (* We can now construct a function from n to {p|qr_spec n p} by composing the objects we already have *) -definition div2P: ∀n.a href="cic:/matita/tutorial/chapter2/Sub.ind(1,0,2)" Sub/a (a href="cic:/matita/tutorial/chapter2/nat.ind(1,0,0)"nat/aa title="Product" href="cic:/fakeuri.def(1)"×/aspan style="text-decoration: underline;"a href="cic:/matita/tutorial/chapter2/bool.ind(1,0,0)"bool/a/span) (a href="cic:/matita/tutorial/chapter2/qr_spec.def(3)"qr_spec/a n) ≝ λn. +img class="anchor" src="icons/tick.png" id="div2P"definition div2P: ∀n. a href="cic:/matita/tutorial/chapter2/Sub.ind(1,0,2)"Sub/a (a href="cic:/matita/tutorial/chapter2/nat.ind(1,0,0)"nat/aa title="Product" href="cic:/fakeuri.def(1)"×/aspan style="text-decoration: underline;"a href="cic:/matita/tutorial/chapter2/bool.ind(1,0,0)"bool/a/span) (a href="cic:/matita/tutorial/chapter2/qr_spec.def(3)"qr_spec/a n) ≝ λn. a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a ?? (a href="cic:/matita/tutorial/chapter2/div2.fix(0,0,2)"div2/a n) (a href="cic:/matita/tutorial/chapter2/div2_ok.def(4)"div2_ok/a n). (* But we can also try do directly build such an object *) -definition div2Pagain : ∀n.a href="cic:/matita/tutorial/chapter2/Sub.ind(1,0,2)"Sub/a (a href="cic:/matita/tutorial/chapter2/nat.ind(1,0,0)"nat/aa title="Product" href="cic:/fakeuri.def(1)"×/aspan style="text-decoration: underline;"/spana href="cic:/matita/tutorial/chapter2/bool.ind(1,0,0)"bool/a) (a href="cic:/matita/tutorial/chapter2/qr_spec.def(3)"qr_spec/a n). +img class="anchor" src="icons/tick.png" id="div2Pagain"definition div2Pagain : ∀n.a href="cic:/matita/tutorial/chapter2/Sub.ind(1,0,2)"Sub/a (a href="cic:/matita/tutorial/chapter2/nat.ind(1,0,0)"nat/aa title="Product" href="cic:/fakeuri.def(1)"×/aspan style="text-decoration: underline;"/spana href="cic:/matita/tutorial/chapter2/bool.ind(1,0,0)"bool/a) (a href="cic:/matita/tutorial/chapter2/qr_spec.def(3)"qr_spec/a n). #n elim n - [@(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉) normalize #q #r #H destruct // + [@(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a,a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a) normalize #q #r #H destruct // |#a * #p #qrspec - cut (p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.def(1)"fst/a … p, a href="cic:/matita/basics/types/snd.def(1)"snd/a … p〉) [//] - cases (a href="cic:/matita/basics/types/snd.def(1)"snd/a … p) - [#H @(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/basics/types/fst.def(1)"fst/a … p),a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉) whd #q #r #H1 destruct @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a span style="text-decoration: underline;">/spana href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a <a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @(qrspec … H) - |#H @(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.def(1)"fst/a … p,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/a〉) whd #q #r #H1 destruct >a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a @(qrspec … H) + cut (p a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p, a href="cic:/matita/basics/types/snd.fix(0,2,1)"snd/a … pa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a) [//] + cases (a href="cic:/matita/basics/types/snd.fix(0,2,1)"snd/a … p) + [#H @(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a (a href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p),a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a) whd #q #r #H1 destruct @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a span style="text-decoration: underline;">/spana href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a + whd in ⊢ (???%); <a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @(qrspec … H) + |#H @(a href="cic:/matita/tutorial/chapter2/Sub.con(0,1,2)"mk_Sub/a … a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/basics/types/fst.fix(0,2,1)"fst/a … p,a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a) whd #q #r #H1 destruct >a href="cic:/matita/tutorial/chapter2/add_S.def(2)"add_S/a @a href="cic:/matita/basics/logic/eq_f.def(3)"eq_f/a @(qrspec … H) ] qed. -example quotient7: a href="cic:/matita/tutorial/chapter2/witness.fix(0,2,1)"witness/a … (a href="cic:/matita/tutorial/chapter2/div2Pagain.def(4)"div2Pagain/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)))))))) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)),a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/a〉. +img class="anchor" src="icons/tick.png" id="quotient7"example quotient7: a href="cic:/matita/tutorial/chapter2/witness.fix(0,2,1)"witness/a … (a href="cic:/matita/tutorial/chapter2/div2Pagain.def(4)"div2Pagain/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)))))))) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a(a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)),a href="cic:/matita/tutorial/chapter2/bool.con(0,1,0)"tt/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a. // qed. -example quotient8: a href="cic:/matita/tutorial/chapter2/witness.fix(0,2,1)"witness/a … (a href="cic:/matita/tutorial/chapter2/div2Pagain.def(4)"div2Pagain/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)))))) - a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a))), a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/a〉. +img class="anchor" src="icons/tick.png" id="quotient8"example quotient8: a href="cic:/matita/tutorial/chapter2/witness.fix(0,2,1)"witness/a … (a href="cic:/matita/tutorial/chapter2/div2Pagain.def(4)"div2Pagain/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a)))))) + a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a title="Pair construction" href="cic:/fakeuri.def(1)"〈/aa href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/twice.def(2)"twice/a (a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"S/a a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"O/a))), a href="cic:/matita/tutorial/chapter2/bool.con(0,2,0)"ff/aa title="Pair construction" href="cic:/fakeuri.def(1)"〉/a. // qed. prepre /pre/pre \ No newline at end of file