Mercurial > cpdt > repo
comparison src/Predicates.v @ 280:15f49309c371
PC's Chapter 4 comments
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Tue, 12 Oct 2010 09:30:17 -0400 |
parents | c4b1c0de7af9 |
children | 4146889930c5 |
comparison
equal
deleted
inserted
replaced
279:fabbc71abd80 | 280:15f49309c371 |
---|---|
110 not = fun A : Prop => A -> False | 110 not = fun A : Prop => A -> False |
111 : Prop -> Prop | 111 : Prop -> Prop |
112 | 112 |
113 ]] | 113 ]] |
114 | 114 |
115 We see that [not] is just shorthand for implication of [False]. We can use that fact explicitly in proofs. The syntax [~P] expands to [not P]. *) | 115 We see that [not] is just shorthand for implication of [False]. We can use that fact explicitly in proofs. The syntax [~ P] expands to [not P]. *) |
116 | 116 |
117 Theorem arith_neq' : ~ (2 + 2 = 5). | 117 Theorem arith_neq' : ~ (2 + 2 = 5). |
118 (* begin thide *) | 118 (* begin thide *) |
119 unfold not. | 119 unfold not. |
120 (** [[ | 120 (** [[ |
496 ============================ | 496 ============================ |
497 1 + 1 = 4 | 497 1 + 1 = 4 |
498 | 498 |
499 ]] | 499 ]] |
500 | 500 |
501 What on earth happened here? Internally, [destruct] replaced [1] with a fresh variable, and, trying to be helpful, it also replaced the occurrence of [1] within the unary representation of each number in the goal. This has the net effect of decrementing each of these numbers. If you are doing a proof and encounter a strange transmutation like this, there is a good chance that you should go back and replace a use of [destruct] with [inversion]. *) | 501 What on earth happened here? Internally, [destruct] replaced [1] with a fresh variable, and, trying to be helpful, it also replaced the occurrence of [1] within the unary representation of each number in the goal. This has the net effect of decrementing each of these numbers. *) |
502 | 502 |
503 Abort. | 503 Abort. |
504 | |
505 (** To see more clearly what is happening, we can consider the type of [isZero]'s induction principle. *) | |
506 | |
507 Check isZero_ind. | |
508 (** %\vspace{-.15in}% [[ | |
509 isZero_ind | |
510 : forall P : nat -> Prop, P 0 -> forall n : nat, isZero n -> P n | |
511 | |
512 ]] | |
513 | |
514 In our last proof script, [destruct] chose to instantiate [P] as [fun n => S n + S n = S (S (S (S n)))]. You can verify for yourself that this specialization of the principle applies to the goal and that the hypothesis [P 0] then matches the subgoal we saw generated. If you are doing a proof and encounter a strange transmutation like this, there is a good chance that you should go back and replace a use of [destruct] with [inversion]. *) | |
504 | 515 |
505 | 516 |
506 (* begin hide *) | 517 (* begin hide *) |
507 (* In-class exercises *) | 518 (* In-class exercises *) |
508 | 519 |
714 subgoal 2 is: | 725 subgoal 2 is: |
715 False | 726 False |
716 | 727 |
717 ]] | 728 ]] |
718 | 729 |
719 We are already sunk trying to prove the first subgoal, since the argument to [even] was replaced by a fresh variable internally. This time, we find it easiest to prove this theorem by way of a lemma. Instead of trusting [induction] to replace expressions with fresh variables, we do it ourselves, explicitly adding the appropriate equalities as new assumptions. *) | 730 We are already sunk trying to prove the first subgoal, since the argument to [even] was replaced by a fresh variable internally. This time, we find it easier to prove this theorem by way of a lemma. Instead of trusting [induction] to replace expressions with fresh variables, we do it ourselves, explicitly adding the appropriate equalities as new assumptions. *) |
720 | 731 |
721 Abort. | 732 Abort. |
722 | 733 |
723 Lemma even_contra' : forall n', even n' -> forall n, n' = S (n + n) -> False. | 734 Lemma even_contra' : forall n', even n' -> forall n, n' = S (n + n) -> False. |
724 induction 1; crush. | 735 induction 1; crush. |
736 ============================ | 747 ============================ |
737 False | 748 False |
738 | 749 |
739 ]] | 750 ]] |
740 | 751 |
741 At this point it is useful to use a theorem from the standard library, which we also proved with a different name in the last chapter. *) | 752 At this point it is useful to use a theorem from the standard library, which we also proved with a different name in the last chapter. We can search for a theorem that allows us to rewrite terms of the form [x + S y]. *) |
742 | 753 |
743 Check plus_n_Sm. | 754 SearchRewrite (_ + S _). |
744 (** %\vspace{-.15in}% [[ | 755 (** %\vspace{-.15in}% [[ |
745 plus_n_Sm | 756 plus_n_Sm : forall n m : nat, S (n + m) = n + S m |
746 : forall n m : nat, S (n + m) = n + S m | |
747 ]] *) | 757 ]] *) |
748 | 758 |
749 rewrite <- plus_n_Sm in H0. | 759 rewrite <- plus_n_Sm in H0. |
750 | 760 |
751 (** The induction hypothesis lets us complete the proof. *) | 761 (** The induction hypothesis lets us complete the proof. *) |
909 match goal with | 919 match goal with |
910 | [ |- context[eq_nat_dec ?X ?Y] ] => destruct (eq_nat_dec X Y) | 920 | [ |- context[eq_nat_dec ?X ?Y] ] => destruct (eq_nat_dec X Y) |
911 end | 921 end |
912 ]] #</li># | 922 ]] #</li># |
913 %\item%#<li># You probably do not want to use an inductive definition for compatibility of variable assignments and typings.#</li># | 923 %\item%#<li># You probably do not want to use an inductive definition for compatibility of variable assignments and typings.#</li># |
914 %\item%#<li># The [Tactics] module from this book contains a variant [crush'] of [crush]. [crush'] takes two arguments. The first argument is a list of lemmas and other functions to be tried automatically in "forward reasoning" style, where we add new facts without being sure yet that they link into a proof of the conclusion. The second argument is a list of predicates on which inverison should be attempted automatically. For instance, running [crush' (lemma1, lemma2) pred] will search for chances to apply [lemma1] and [lemma2] to hypotheses that are already available, adding the new concluded fact if suitable hypotheses can be found. Inversion will be attempted on any hypothesis using [pred], but only those inversions that narrow the field of possibilities to one possible rule will be kept. The format of the list arguments to [crush'] is that you can pass an empty list as [tt], a singleton list as the unadorned single element, and a multiple-element list as a tuple of the elements.#</li># | 924 %\item%#<li># The [Tactics] module from this book contains a variant [crush'] of [crush]. [crush'] takes two arguments. The first argument is a list of lemmas and other functions to be tried automatically in "forward reasoning" style, where we add new facts without being sure yet that they link into a proof of the conclusion. The second argument is a list of predicates on which inversion should be attempted automatically. For instance, running [crush' (lemma1, lemma2) pred] will search for chances to apply [lemma1] and [lemma2] to hypotheses that are already available, adding the new concluded fact if suitable hypotheses can be found. Inversion will be attempted on any hypothesis using [pred], but only those inversions that narrow the field of possibilities to one possible rule will be kept. The format of the list arguments to [crush'] is that you can pass an empty list as [tt], a singleton list as the unadorned single element, and a multiple-element list as a tuple of the elements.#</li># |
915 %\item%#<li># If you want [crush'] to apply polymorphic lemmas, you may have to do a little extra work, if the type parameter is not a free variable of your proof context (so that [crush'] does not know to try it). For instance, if you define a polymorphic map insert function [assign] of some type [forall T : Set, ...], and you want particular applications of [assign] added automatically with type parameter [U], you would need to include [assign] in the lemma list as [assign U] (if you have implicit arguments off) or [assign (T := U)] or [@assign U] (if you have implicit arguments on).#</li># | 925 %\item%#<li># If you want [crush'] to apply polymorphic lemmas, you may have to do a little extra work, if the type parameter is not a free variable of your proof context (so that [crush'] does not know to try it). For instance, if you define a polymorphic map insert function [assign] of some type [forall T : Set, ...], and you want particular applications of [assign] added automatically with type parameter [U], you would need to include [assign] in the lemma list as [assign U] (if you have implicit arguments off) or [assign (T := U)] or [@assign U] (if you have implicit arguments on).#</li># |
916 #</ol> </li>#%\end{enumerate}% | 926 #</ol> </li>#%\end{enumerate}% |
917 | 927 |
918 #</li># | 928 #</li># |
919 | 929 |