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