X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=weblib%2Ftutorial%2Fchapter2.ma;h=6784de617d3c5462cbba74856bc80079ed70e974;hb=48c011f52853dd106dbf9cbbd1b9da61277fba3b;hp=d6e5a82b8307f2e9a6ec306540f9bc174c90b15f;hpb=de42a5affe63ef848353265010f372c737befb39;p=helm.git diff --git a/weblib/tutorial/chapter2.ma b/weblib/tutorial/chapter2.ma index d6e5a82b8..6784de617 100644 --- a/weblib/tutorial/chapter2.ma +++ b/weblib/tutorial/chapter2.ma @@ -1,50 +1,55 @@ -include "basics/logic.ma". - -(* Most of the types we have seen so far are enumerated types, composed by -a finite set of alternatives, and records, composed by tuples of -heteregoneous elements. A more interesting case of type definition is -when some of the rules defining its elements are recursive, i.e. they -allow the formation of more elements of the type in terms of the already -defined ones. The most typical case 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] ≝ +(* +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 +finite set of alternatives, and records, composed by tuples of heteregoneous +elements. A more interesting case of type definition is when some of the rules +defining its elements are recursive, i.e. they allow the formation of more +elements of the type in terms of the already defined ones. The most typical case +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 *) + +img class="anchor" src="icons/tick.png" id="nat"inductive nat : Type[0] ≝ | O :nat | S: nat →nat. -(* The two terms O and S are called constructors: they define the -signature of the type, whose objects are the elements freely generated -by means of them. So, examples of natural numbers are O, S O, S (S O), -S (S (S O)) and so on. +(* The two terms O and S are called constructors: they define the signature of the +type, whose objects are the elements freely generated by means of them. So, +examples of natural numbers are O, S O, S (S O), S (S (S O)) and so on. -The language of Matita allows the definition of well founded recursive functions -over inductive types; in order to guarantee termination of recursion you are -only allowed to make recursive calls on structurally smaller arguments than the -ones your 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 *) +The language of Matita allows the definition of well founded recursive functions +over inductive types; in order to guarantee termination of recursion you are only +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 -first argument. This means that, for instance, (add 0 x) will reduce to x, as expected, -but (add x 0) is stack. How can we prove that, for a generic x, (add x 0) = x? The -mathematical tool do it is called induction. The induction principle states that, -given a property P(n) over natural numbers, if we prove P(0) and prove that, for any -m, P(m) implies P(S m), than we can conclude P(n) for any n. +(* +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 +it is called induction. The induction principle states that, given a property P(n) +over natural numbers, if we prove P(0) and prove that, for any m, P(m) implies P(S m), +than we can conclude P(n) for any n. -The elim tactic, allow you to apply induction in a vcery simple way. If your -goal is P(n), the invocation of +The elim tactic, allow you to apply induction in a very simple way. If your goal is +P(n), the invocation of elim n 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 @@ -55,10 +60,10 @@ After normalization, both goals are trivial. 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. *) +(* 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,35 +72,216 @@ 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: G1: ∀b. b = add b O G2: ∀x.(∀b. add x b = add b x) → ∀b. S (add x b) = add b (S x). -G1 is just our lemma add_O. For G2, we start introducing x and the induction +G1 is just our lemma add_O. For G2, we start introducing x and the induction hypothesis IH; then, the goal is proved by rewriting using add_S and IH. For Matita, the task is trivial and we can simply close the goal with // *) // qed. +(* COERCIONS *) + +img class="anchor" src="icons/tick.png" id="bool"inductive bool : Type[0] ≝ +| tt : bool +| ff : bool. + +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 +]. + +(* coercion nat_of_bool. ?? *) + (* 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 m there -exists a natural number m that is the integer half of m. This -will give us the opportunity to introduce new connectives -and quantifiers, and later on to make some interesting consideration -on proofs and computations. *) +(* +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: + G1: ∃m.O = add O O ∨ O = S (add m m) + G2: ∀x.(∃m. x = add m m ∨ x = S (add m m))→ ∃m. S x = add m m ∨ S x = S (add m m) +The only way we have to prove an existential goal is by exhibiting the witness, +that in the case of first goal is O. We do it by apply the term called ex_intro +instantiated by the witness. Then, it is clear that we must follow the left branch +of the disjunction. One way to do it is by applying the term or_introl, that is +the first constructor of the disjunction. However, remembering the names of +constructors can be annyoing: we can invoke the application of the n-th +constructor of an inductive type (inferred by the current goal) by typing %n. At +this point we are left with the subgoal O = add O O, that is closed by +computation. It is worth to observe that invoking automation at depth /3/ would +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 // -(* *) - |#x * #m * #eqx - [@(a href="cic:/matita/basics/logic/ex.con(0,1,2)"ex_intro/a … m) /2/ | @(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 /2/ + +(* +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 + (∃x.P x) → Q +to a goal of the shape + ∀x.P x → Q +*) + |#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 + 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. +*) + [@(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. + +(* +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.*) + +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/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.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. + +Let us now prove that our div2 function has the expected behaviour. +*) + +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. + +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. + +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. + +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.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. + +(* +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. +*) + +img class="anchor" src="icons/tick.png" id="Sub"record Sub (A:Type[0]) (P:A → Prop) : Type[0] ≝ + {witness: A; + proof: P witness}. + +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 *) + +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 *) + +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/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.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. + +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. + +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