comparison src/InductiveTypes.v @ 41:d45ba7e9b266

Improve template generation; craft template for InductiveTypes
author Adam Chlipala <adamc@hcoop.net>
date Sat, 13 Sep 2008 14:31:51 -0400
parents 02e8e9ef2746
children 9bdbc43d510e
comparison
equal deleted inserted replaced
40:02e8e9ef2746 41:d45ba7e9b266
45 45
46 (** We can prove that [unit] is a genuine singleton type. *) 46 (** We can prove that [unit] is a genuine singleton type. *)
47 47
48 Theorem unit_singleton : forall x : unit, x = tt. 48 Theorem unit_singleton : forall x : unit, x = tt.
49 (** The important thing about an inductive type is, unsurprisingly, that you can do induction over its values, and induction is the key to proving this theorem. We ask to proceed by induction on the variable [x]. *) 49 (** The important thing about an inductive type is, unsurprisingly, that you can do induction over its values, and induction is the key to proving this theorem. We ask to proceed by induction on the variable [x]. *)
50 (* begin thide *)
50 induction x. 51 induction x.
51 (** The goal changes to: [[ 52 (** The goal changes to: [[
52 53
53 tt = tt 54 tt = tt
54 ]] *) 55 ]] *)
55 (** ...which we can discharge trivially. *) 56 (** ...which we can discharge trivially. *)
56 reflexivity. 57 reflexivity.
57 Qed. 58 Qed.
59 (* end thide *)
58 60
59 (** It seems kind of odd to write a proof by induction with no inductive hypotheses. We could have arrived at the same result by beginning the proof with: [[ 61 (** It seems kind of odd to write a proof by induction with no inductive hypotheses. We could have arrived at the same result by beginning the proof with: [[
60 62
61 destruct x. 63 destruct x.
62 ...which corresponds to "proof by case analysis" in classical math. For non-recursive inductive types, the two tactics will always have identical behavior. Often case analysis is sufficient, even in proofs about recursive types, and it is nice to avoid introducing unneeded induction hypotheses. 64 ...which corresponds to "proof by case analysis" in classical math. For non-recursive inductive types, the two tactics will always have identical behavior. Often case analysis is sufficient, even in proofs about recursive types, and it is nice to avoid introducing unneeded induction hypotheses.
82 Inductive Empty_set : Set := . 84 Inductive Empty_set : Set := .
83 85
84 (** [Empty_set] has no elements. We can prove fun theorems about it: *) 86 (** [Empty_set] has no elements. We can prove fun theorems about it: *)
85 87
86 Theorem the_sky_is_falling : forall x : Empty_set, 2 + 2 = 5. 88 Theorem the_sky_is_falling : forall x : Empty_set, 2 + 2 = 5.
89 (* begin thide *)
87 destruct 1. 90 destruct 1.
88 Qed. 91 Qed.
92 (* end thide *)
89 93
90 (** Because [Empty_set] has no elements, the fact of having an element of this type implies anything. We use [destruct 1] instead of [destruct x] in the proof because unused quantified variables are relegated to being referred to by number. (There is a good reason for this, related to the unity of quantifiers and implication. An implication is just a quantification over a proof, where the quantified variable is never used. It generally makes more sense to refer to implication hypotheses by number than by name, and Coq treats our quantifier over an unused variable as an implication in determining the proper behavior.) 94 (** Because [Empty_set] has no elements, the fact of having an element of this type implies anything. We use [destruct 1] instead of [destruct x] in the proof because unused quantified variables are relegated to being referred to by number. (There is a good reason for this, related to the unity of quantifiers and implication. An implication is just a quantification over a proof, where the quantified variable is never used. It generally makes more sense to refer to implication hypotheses by number than by name, and Coq treats our quantifier over an unused variable as an implication in determining the proper behavior.)
91 95
92 We can see the induction principle that made this proof so easy: *) 96 We can see the induction principle that made this proof so easy: *)
93 97
127 if b then false else true. 131 if b then false else true.
128 132
129 (** We might want to prove that [not] is its own inverse operation. *) 133 (** We might want to prove that [not] is its own inverse operation. *)
130 134
131 Theorem not_inverse : forall b : bool, not (not b) = b. 135 Theorem not_inverse : forall b : bool, not (not b) = b.
136 (* begin thide *)
132 destruct b. 137 destruct b.
133 138
134 (** After we case analyze on [b], we are left with one subgoal for each constructor of [bool]. 139 (** After we case analyze on [b], we are left with one subgoal for each constructor of [bool].
135 140
136 [[ 141 [[
153 (** Likewise for the second subgoal, so we can restart the proof and give a very compact justification. *) 158 (** Likewise for the second subgoal, so we can restart the proof and give a very compact justification. *)
154 159
155 Restart. 160 Restart.
156 destruct b; reflexivity. 161 destruct b; reflexivity.
157 Qed. 162 Qed.
163 (* end thide *)
158 164
159 (** Another theorem about booleans illustrates another useful tactic. *) 165 (** Another theorem about booleans illustrates another useful tactic. *)
160 166
161 Theorem not_ineq : forall b : bool, not b <> b. 167 Theorem not_ineq : forall b : bool, not b <> b.
168 (* begin thide *)
162 destruct b; discriminate. 169 destruct b; discriminate.
163 Qed. 170 Qed.
171 (* end thide *)
164 172
165 (** [discriminate] is used to prove that two values of an inductive type are not equal, whenever the values are formed with different constructors. In this case, the different constructors are [true] and [false]. 173 (** [discriminate] is used to prove that two values of an inductive type are not equal, whenever the values are formed with different constructors. In this case, the different constructors are [true] and [false].
166 174
167 At this point, it is probably not hard to guess what the underlying induction principle for [bool] is. *) 175 At this point, it is probably not hard to guess what the underlying induction principle for [bool] is. *)
168 176
198 end. 206 end.
199 207
200 (** We can prove theorems by case analysis: *) 208 (** We can prove theorems by case analysis: *)
201 209
202 Theorem S_isZero : forall n : nat, isZero (pred (S (S n))) = false. 210 Theorem S_isZero : forall n : nat, isZero (pred (S (S n))) = false.
211 (* begin thide *)
203 destruct n; reflexivity. 212 destruct n; reflexivity.
204 Qed. 213 Qed.
214 (* end thide *)
205 215
206 (** We can also now get into genuine inductive theorems. First, we will need a recursive function, to make things interesting. *) 216 (** We can also now get into genuine inductive theorems. First, we will need a recursive function, to make things interesting. *)
207 217
208 Fixpoint plus (n m : nat) {struct n} : nat := 218 Fixpoint plus (n m : nat) {struct n} : nat :=
209 match n with 219 match n with
214 (** Recall that [Fixpoint] is Coq's mechanism for recursive function definitions, and that the [{struct n}] annotation is noting which function argument decreases structurally at recursive calls. 224 (** Recall that [Fixpoint] is Coq's mechanism for recursive function definitions, and that the [{struct n}] annotation is noting which function argument decreases structurally at recursive calls.
215 225
216 Some theorems about [plus] can be proved without induction. *) 226 Some theorems about [plus] can be proved without induction. *)
217 227
218 Theorem O_plus_n : forall n : nat, plus O n = n. 228 Theorem O_plus_n : forall n : nat, plus O n = n.
229 (* begin thide *)
219 intro; reflexivity. 230 intro; reflexivity.
220 Qed. 231 Qed.
232 (* end thide *)
221 233
222 (** Coq's computation rules automatically simplify the application of [plus]. If we just reverse the order of the arguments, though, this no longer works, and we need induction. *) 234 (** Coq's computation rules automatically simplify the application of [plus]. If we just reverse the order of the arguments, though, this no longer works, and we need induction. *)
223 235
224 Theorem n_plus_O : forall n : nat, plus n O = n. 236 Theorem n_plus_O : forall n : nat, plus n O = n.
237 (* begin thide *)
225 induction n. 238 induction n.
226 239
227 (** Our first subgoal is [plus O O = O], which %\textit{%#<i>#is#</i>#%}% trivial by computation. *) 240 (** Our first subgoal is [plus O O = O], which %\textit{%#<i>#is#</i>#%}% trivial by computation. *)
228 241
229 reflexivity. 242 reflexivity.
253 (** Not much really went on in this proof, so the [crush] tactic from the [Tactics] module can prove this theorem automatically. *) 266 (** Not much really went on in this proof, so the [crush] tactic from the [Tactics] module can prove this theorem automatically. *)
254 267
255 Restart. 268 Restart.
256 induction n; crush. 269 induction n; crush.
257 Qed. 270 Qed.
271 (* end thide *)
258 272
259 (** We can check out the induction principle at work here: *) 273 (** We can check out the induction principle at work here: *)
260 274
261 Check nat_ind. 275 Check nat_ind.
262 (** [[ 276 (** [[
268 Each of the two cases of our last proof came from the type of one of the arguments to [nat_ind]. We chose [P] to be [(fun n : nat => plus n O = n)]. The first proof case corresponded to [P O], and the second case to [(forall n : nat, P n -> P (S n))]. The free variable [n] and inductive hypothesis [IHn] came from the argument types given here. 282 Each of the two cases of our last proof came from the type of one of the arguments to [nat_ind]. We chose [P] to be [(fun n : nat => plus n O = n)]. The first proof case corresponded to [P O], and the second case to [(forall n : nat, P n -> P (S n))]. The free variable [n] and inductive hypothesis [IHn] came from the argument types given here.
269 283
270 Since [nat] has a constructor that takes an argument, we may sometimes need to know that that constructor is injective. *) 284 Since [nat] has a constructor that takes an argument, we may sometimes need to know that that constructor is injective. *)
271 285
272 Theorem S_inj : forall n m : nat, S n = S m -> n = m. 286 Theorem S_inj : forall n m : nat, S n = S m -> n = m.
287 (* begin thide *)
273 injection 1; trivial. 288 injection 1; trivial.
274 Qed. 289 Qed.
290 (* end thide *)
275 291
276 (** [injection] refers to a premise by number, adding new equalities between the corresponding arguments of equated terms that are formed with the same constructor. We end up needing to prove [n = m -> n = m], so it is unsurprising that a tactic named [trivial] is able to finish the proof. 292 (** [injection] refers to a premise by number, adding new equalities between the corresponding arguments of equated terms that are formed with the same constructor. We end up needing to prove [n = m -> n = m], so it is unsurprising that a tactic named [trivial] is able to finish the proof.
277 293
278 There is also a very useful tactic called [congruence] that can prove this theorem immediately. [congruence] generalizes [discriminate] and [injection], and it also adds reasoning about the general properties of equality, such as that a function returns equal results on equal arguments. That is, [congruence] is a %\textit{%#<i>#complete decision procedure for the theory of equality and uninterpreted functions#</i>#%}%, plus some smarts about inductive types. 294 There is also a very useful tactic called [congruence] that can prove this theorem immediately. [congruence] generalizes [discriminate] and [injection], and it also adds reasoning about the general properties of equality, such as that a function returns equal results on equal arguments. That is, [congruence] is a %\textit{%#<i>#complete decision procedure for the theory of equality and uninterpreted functions#</i>#%}%, plus some smarts about inductive types.
279 295
301 317
302 (** Inductive theorem proving can again be automated quite effectively. *) 318 (** Inductive theorem proving can again be automated quite effectively. *)
303 319
304 Theorem nlength_napp : forall ls1 ls2 : nat_list, nlength (napp ls1 ls2) 320 Theorem nlength_napp : forall ls1 ls2 : nat_list, nlength (napp ls1 ls2)
305 = plus (nlength ls1) (nlength ls2). 321 = plus (nlength ls1) (nlength ls2).
322 (* begin thide *)
306 induction ls1; crush. 323 induction ls1; crush.
307 Qed. 324 Qed.
325 (* end thide *)
308 326
309 Check nat_list_ind. 327 Check nat_list_ind.
310 (** [[ 328 (** [[
311 329
312 nat_list_ind 330 nat_list_ind
335 | NLeaf => NNode tr2 O NLeaf 353 | NLeaf => NNode tr2 O NLeaf
336 | NNode tr1' n tr2' => NNode (nsplice tr1' tr2) n tr2' 354 | NNode tr1' n tr2' => NNode (nsplice tr1' tr2) n tr2'
337 end. 355 end.
338 356
339 Theorem plus_assoc : forall n1 n2 n3 : nat, plus (plus n1 n2) n3 = plus n1 (plus n2 n3). 357 Theorem plus_assoc : forall n1 n2 n3 : nat, plus (plus n1 n2) n3 = plus n1 (plus n2 n3).
358 (* begin thide *)
340 induction n1; crush. 359 induction n1; crush.
341 Qed. 360 Qed.
361 (* end thide *)
342 362
343 Theorem nsize_nsplice : forall tr1 tr2 : nat_btree, nsize (nsplice tr1 tr2) 363 Theorem nsize_nsplice : forall tr1 tr2 : nat_btree, nsize (nsplice tr1 tr2)
344 = plus (nsize tr2) (nsize tr1). 364 = plus (nsize tr2) (nsize tr1).
365 (* begin thide *)
345 Hint Rewrite n_plus_O plus_assoc : cpdt. 366 Hint Rewrite n_plus_O plus_assoc : cpdt.
346 367
347 induction tr1; crush. 368 induction tr1; crush.
348 Qed. 369 Qed.
370 (* end thide *)
349 371
350 Check nat_btree_ind. 372 Check nat_btree_ind.
351 (** [[ 373 (** [[
352 374
353 nat_btree_ind 375 nat_btree_ind
379 | Cons x ls1' => Cons x (app ls1' ls2) 401 | Cons x ls1' => Cons x (app ls1' ls2)
380 end. 402 end.
381 403
382 Theorem length_app : forall T (ls1 ls2 : list T), length (app ls1 ls2) 404 Theorem length_app : forall T (ls1 ls2 : list T), length (app ls1 ls2)
383 = plus (length ls1) (length ls2). 405 = plus (length ls1) (length ls2).
406 (* begin thide *)
384 induction ls1; crush. 407 induction ls1; crush.
385 Qed. 408 Qed.
409 (* end thide *)
386 410
387 (** There is a useful shorthand for writing many definitions that share the same parameter, based on Coq's %\textit{%#<i>#section#</i>#%}% mechanism. The following block of code is equivalent to the above: *) 411 (** There is a useful shorthand for writing many definitions that share the same parameter, based on Coq's %\textit{%#<i>#section#</i>#%}% mechanism. The following block of code is equivalent to the above: *)
388 412
389 (* begin hide *) 413 (* begin hide *)
390 Reset list. 414 Reset list.
409 | Cons x ls1' => Cons x (app ls1' ls2) 433 | Cons x ls1' => Cons x (app ls1' ls2)
410 end. 434 end.
411 435
412 Theorem length_app : forall ls1 ls2 : list, length (app ls1 ls2) 436 Theorem length_app : forall ls1 ls2 : list, length (app ls1 ls2)
413 = plus (length ls1) (length ls2). 437 = plus (length ls1) (length ls2).
438 (* begin thide *)
414 induction ls1; crush. 439 induction ls1; crush.
415 Qed. 440 Qed.
441 (* end thide *)
416 End list. 442 End list.
417 443
418 (* begin hide *) 444 (* begin hide *)
419 Implicit Arguments Nil [T]. 445 Implicit Arguments Nil [T].
420 (* end hide *) 446 (* end hide *)
492 518
493 (** Everything is going roughly the same as in past examples, until we try to prove a theorem similar to those that came before. *) 519 (** Everything is going roughly the same as in past examples, until we try to prove a theorem similar to those that came before. *)
494 520
495 Theorem elength_eapp : forall el1 el2 : even_list, 521 Theorem elength_eapp : forall el1 el2 : even_list,
496 elength (eapp el1 el2) = plus (elength el1) (elength el2). 522 elength (eapp el1 el2) = plus (elength el1) (elength el2).
523 (* begin thide *)
497 induction el1; crush. 524 induction el1; crush.
498 525
499 (** One goal remains: [[ 526 (** One goal remains: [[
500 527
501 n : nat 528 n : nat
544 571
545 This technique generalizes to our mutual example: *) 572 This technique generalizes to our mutual example: *)
546 573
547 Theorem elength_eapp : forall el1 el2 : even_list, 574 Theorem elength_eapp : forall el1 el2 : even_list,
548 elength (eapp el1 el2) = plus (elength el1) (elength el2). 575 elength (eapp el1 el2) = plus (elength el1) (elength el2).
576
549 apply (even_list_mut 577 apply (even_list_mut
550 (fun el1 : even_list => forall el2 : even_list, 578 (fun el1 : even_list => forall el2 : even_list,
551 elength (eapp el1 el2) = plus (elength el1) (elength el2)) 579 elength (eapp el1 el2) = plus (elength el1) (elength el2))
552 (fun ol : odd_list => forall el : even_list, 580 (fun ol : odd_list => forall el : even_list,
553 olength (oapp ol el) = plus (olength ol) (elength el))); crush. 581 olength (oapp ol el) = plus (olength ol) (elength el))); crush.
554 Qed. 582 Qed.
583 (* end thide *)
555 584
556 (** We simply need to specify two predicates, one for each of the mutually inductive types. In general, it would not be a good idea to assume that a proof assistant could infer extra predicates, so this way of applying mutual induction is about as straightforward as we could hope for. *) 585 (** We simply need to specify two predicates, one for each of the mutually inductive types. In general, it would not be a good idea to assume that a proof assistant could infer extra predicates, so this way of applying mutual induction is about as straightforward as we could hope for. *)
557 586
558 587
559 (** * Reflexive Types *) 588 (** * Reflexive Types *)
588 end. 617 end.
589 618
590 (** It is helpful to prove that this transformation does not make true formulas false. *) 619 (** It is helpful to prove that this transformation does not make true formulas false. *)
591 620
592 Theorem swapper_preserves_truth : forall f, formulaDenote f -> formulaDenote (swapper f). 621 Theorem swapper_preserves_truth : forall f, formulaDenote f -> formulaDenote (swapper f).
622 (* begin thide *)
593 induction f; crush. 623 induction f; crush.
594 Qed. 624 Qed.
625 (* end thide *)
595 626
596 (** We can take a look at the induction principle behind this proof. *) 627 (** We can take a look at the induction principle behind this proof. *)
597 628
598 Check formula_ind. 629 Check formula_ind.
599 (** [[ 630 (** [[
967 | NNode' n (Cons tr trs) => NNode' n (Cons (ntsplice tr tr2) trs) 998 | NNode' n (Cons tr trs) => NNode' n (Cons (ntsplice tr tr2) trs)
968 end. 999 end.
969 1000
970 (** We have defined another arbitrary notion of tree splicing, similar to before, and we can prove an analogous theorem about its relationship with tree size. We start with a useful lemma about addition. *) 1001 (** We have defined another arbitrary notion of tree splicing, similar to before, and we can prove an analogous theorem about its relationship with tree size. We start with a useful lemma about addition. *)
971 1002
1003 (* begin thide *)
972 Lemma plus_S : forall n1 n2 : nat, 1004 Lemma plus_S : forall n1 n2 : nat,
973 plus n1 (S n2) = S (plus n1 n2). 1005 plus n1 (S n2) = S (plus n1 n2).
974 induction n1; crush. 1006 induction n1; crush.
975 Qed. 1007 Qed.
1008 (* end thide *)
976 1009
977 (** Now we begin the proof of the theorem, adding the lemma [plus_S] as a hint. *) 1010 (** Now we begin the proof of the theorem, adding the lemma [plus_S] as a hint. *)
978 1011
979 Theorem ntsize_ntsplice : forall tr1 tr2 : nat_tree, ntsize (ntsplice tr1 tr2) 1012 Theorem ntsize_ntsplice : forall tr1 tr2 : nat_tree, ntsize (ntsplice tr1 tr2)
980 = plus (ntsize tr2) (ntsize tr1). 1013 = plus (ntsize tr2) (ntsize tr1).
1014 (* begin thide *)
981 Hint Rewrite plus_S : cpdt. 1015 Hint Rewrite plus_S : cpdt.
982 1016
983 (** We know that the standard induction principle is insufficient for the task, so we need to provide a [using] clause for the [induction] tactic to specify our alternate principle. *) 1017 (** We know that the standard induction principle is insufficient for the task, so we need to provide a [using] clause for the [induction] tactic to specify our alternate principle. *)
984 induction tr1 using nat_tree_ind'; crush. 1018 induction tr1 using nat_tree_ind'; crush.
985 1019
1009 Restart. 1043 Restart.
1010 Hint Extern 1 (ntsize (match ?LS with Nil => _ | Cons _ _ => _ end) = _) => 1044 Hint Extern 1 (ntsize (match ?LS with Nil => _ | Cons _ _ => _ end) = _) =>
1011 destruct LS; crush. 1045 destruct LS; crush.
1012 induction tr1 using nat_tree_ind'; crush. 1046 induction tr1 using nat_tree_ind'; crush.
1013 Qed. 1047 Qed.
1048 (* end thide *)
1014 1049
1015 (** We will go into great detail on hints in a later chapter, but the only important thing to note here is that we register a pattern that describes a conclusion we expect to encounter during the proof. The pattern may contain unification variables, whose names are prefixed with question marks, and we may refer to those bound variables in a tactic that we ask to have run whenever the pattern matches. 1050 (** We will go into great detail on hints in a later chapter, but the only important thing to note here is that we register a pattern that describes a conclusion we expect to encounter during the proof. The pattern may contain unification variables, whose names are prefixed with question marks, and we may refer to those bound variables in a tactic that we ask to have run whenever the pattern matches.
1016 1051
1017 The advantage of using the hint is not very clear here, because the original proof was so short. However, the hint has fundamentally improved the readability of our proof. Before, the proof referred to the local variable [ls], which has an automatically-generated name. To a human reading the proof script without stepping through it interactively, it was not clear where [ls] came from. The hint explains to the reader the process for choosing which variables to case analyze on, and the hint can continue working even if the rest of the proof structure changes significantly. *) 1052 The advantage of using the hint is not very clear here, because the original proof was so short. However, the hint has fundamentally improved the readability of our proof. Before, the proof referred to the local variable [ls], which has an automatically-generated name. To a human reading the proof script without stepping through it interactively, it was not clear where [ls] came from. The hint explains to the reader the process for choosing which variables to case analyze on, and the hint can continue working even if the rest of the proof structure changes significantly. *)
1018 1053
1020 (** * Manual Proofs About Constructors *) 1055 (** * Manual Proofs About Constructors *)
1021 1056
1022 (** It can be useful to understand how tactics like [discriminate] and [injection] work, so it is worth stepping through a manual proof of each kind. We will start with a proof fit for [discriminate]. *) 1057 (** It can be useful to understand how tactics like [discriminate] and [injection] work, so it is worth stepping through a manual proof of each kind. We will start with a proof fit for [discriminate]. *)
1023 1058
1024 Theorem true_neq_false : true <> false. 1059 Theorem true_neq_false : true <> false.
1060 (* begin thide *)
1025 (** We begin with the tactic [red], which is short for "one step of reduction," to unfold the definition of logical negation. *) 1061 (** We begin with the tactic [red], which is short for "one step of reduction," to unfold the definition of logical negation. *)
1026 1062
1027 red. 1063 red.
1028 (** [[ 1064 (** [[
1029 1065
1075 True 1111 True
1076 ]] *) 1112 ]] *)
1077 1113
1078 trivial. 1114 trivial.
1079 Qed. 1115 Qed.
1116 (* end thide *)
1080 1117
1081 (** I have no trivial automated version of this proof to suggest, beyond using [discriminate] or [congruence] in the first place. 1118 (** I have no trivial automated version of this proof to suggest, beyond using [discriminate] or [congruence] in the first place.
1082 1119
1083 %\medskip% 1120 %\medskip%
1084 1121
1085 We can perform a similar manual proof of injectivity of the constructor [S]. I leave a walk-through of the details to curious readers who want to run the proof script interactively. *) 1122 We can perform a similar manual proof of injectivity of the constructor [S]. I leave a walk-through of the details to curious readers who want to run the proof script interactively. *)
1086 1123
1087 Theorem S_inj' : forall n m : nat, S n = S m -> n = m. 1124 Theorem S_inj' : forall n m : nat, S n = S m -> n = m.
1125 (* begin thide *)
1088 intros n m H. 1126 intros n m H.
1089 change (pred (S n) = pred (S m)). 1127 change (pred (S n) = pred (S m)).
1090 rewrite H. 1128 rewrite H.
1091 reflexivity. 1129 reflexivity.
1092 Qed. 1130 Qed.
1131 (* end thide *)
1093 1132
1094 1133
1095 (** * Exercises *) 1134 (** * Exercises *)
1096 1135
1097 (** %\begin{enumerate}%#<ol># 1136 (** %\begin{enumerate}%#<ol>#