Mercurial > cpdt > repo
comparison src/Predicates.v @ 302:7b38729be069
Tweak mark-up to support coqdoc 8.3
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Mon, 17 Jan 2011 15:12:30 -0500 |
parents | 2c88fc1dbe33 |
children | d5787b70cf48 |
comparison
equal
deleted
inserted
replaced
301:f4768d5a75eb | 302:7b38729be069 |
---|---|
21 (** The so-called %``%#"#Curry-Howard Correspondence#"#%''% states a formal connection between functional programs and mathematical proofs. In the last chapter, we snuck in a first introduction to this subject in Coq. Witness the close similarity between the types [unit] and [True] from the standard library: *) | 21 (** The so-called %``%#"#Curry-Howard Correspondence#"#%''% states a formal connection between functional programs and mathematical proofs. In the last chapter, we snuck in a first introduction to this subject in Coq. Witness the close similarity between the types [unit] and [True] from the standard library: *) |
22 | 22 |
23 Print unit. | 23 Print unit. |
24 (** %\vspace{-.15in}% [[ | 24 (** %\vspace{-.15in}% [[ |
25 Inductive unit : Set := tt : unit | 25 Inductive unit : Set := tt : unit |
26 ]] *) | 26 ]] |
27 *) | |
27 | 28 |
28 Print True. | 29 Print True. |
29 (** %\vspace{-.15in}% [[ | 30 (** %\vspace{-.15in}% [[ |
30 Inductive True : Prop := I : True | 31 Inductive True : Prop := I : True |
31 ]] *) | 32 ]] |
33 *) | |
32 | 34 |
33 (** Recall that [unit] is the type with only one value, and [True] is the proposition that always holds. Despite this superficial difference between the two concepts, in both cases we can use the same inductive definition mechanism. The connection goes further than this. We see that we arrive at the definition of [True] by replacing [unit] by [True], [tt] by [I], and [Set] by [Prop]. The first two of these differences are superficial changes of names, while the third difference is the crucial one for separating programs from proofs. A term [T] of type [Set] is a type of programs, and a term of type [T] is a program. A term [T] of type [Prop] is a logical proposition, and its proofs are of type [T]. | 35 (** Recall that [unit] is the type with only one value, and [True] is the proposition that always holds. Despite this superficial difference between the two concepts, in both cases we can use the same inductive definition mechanism. The connection goes further than this. We see that we arrive at the definition of [True] by replacing [unit] by [True], [tt] by [I], and [Set] by [Prop]. The first two of these differences are superficial changes of names, while the third difference is the crucial one for separating programs from proofs. A term [T] of type [Set] is a type of programs, and a term of type [T] is a program. A term [T] of type [Prop] is a logical proposition, and its proofs are of type [T]. |
34 | 36 |
35 [unit] has one value, [tt]. [True] has one proof, [I]. Why distinguish between these two types? Many people who have read about Curry-Howard in an abstract context and not put it to use in proof engineering answer that the two types in fact %\textit{%#<i>#should not#</i>#%}% be distinguished. There is a certain aesthetic appeal to this point of view, but I want to argue that it is best to treat Curry-Howard very loosely in practical proving. There are Coq-specific reasons for preferring the distinction, involving efficient compilation and avoidance of paradoxes in the presence of classical math, but I will argue that there is a more general principle that should lead us to avoid conflating programming and proving. | 37 [unit] has one value, [tt]. [True] has one proof, [I]. Why distinguish between these two types? Many people who have read about Curry-Howard in an abstract context and not put it to use in proof engineering answer that the two types in fact %\textit{%#<i>#should not#</i>#%}% be distinguished. There is a certain aesthetic appeal to this point of view, but I want to argue that it is best to treat Curry-Howard very loosely in practical proving. There are Coq-specific reasons for preferring the distinction, involving efficient compilation and avoidance of paradoxes in the presence of classical math, but I will argue that there is a more general principle that should lead us to avoid conflating programming and proving. |
36 | 38 |
118 (* begin thide *) | 120 (* begin thide *) |
119 unfold not. | 121 unfold not. |
120 (** [[ | 122 (** [[ |
121 ============================ | 123 ============================ |
122 2 + 2 = 5 -> False | 124 2 + 2 = 5 -> False |
123 ]] *) | 125 ]] |
126 *) | |
124 | 127 |
125 crush. | 128 crush. |
126 (* end thide *) | 129 (* end thide *) |
127 Qed. | 130 Qed. |
128 | 131 |
212 1 subgoal | 215 1 subgoal |
213 | 216 |
214 H : Q | 217 H : Q |
215 ============================ | 218 ============================ |
216 Q \/ P | 219 Q \/ P |
217 ]] *) | 220 ]] |
221 *) | |
218 | 222 |
219 left; assumption. | 223 left; assumption. |
220 (* end thide *) | 224 (* end thide *) |
221 Qed. | 225 Qed. |
222 | 226 |
364 (** The conclusion is replaced with a version using the existential witness that we announced. | 368 (** The conclusion is replaced with a version using the existential witness that we announced. |
365 | 369 |
366 [[ | 370 [[ |
367 ============================ | 371 ============================ |
368 1 + 1 = 2 | 372 1 + 1 = 2 |
369 ]] *) | 373 ]] |
374 *) | |
370 | 375 |
371 reflexivity. | 376 reflexivity. |
372 (* end thide *) | 377 (* end thide *) |
373 Qed. | 378 Qed. |
374 | 379 |
639 | 644 |
640 simpl. | 645 simpl. |
641 (** [[ | 646 (** [[ |
642 ============================ | 647 ============================ |
643 even (S (S (n0 + m))) | 648 even (S (S (n0 + m))) |
644 ]] *) | 649 ]] |
650 *) | |
645 | 651 |
646 constructor. | 652 constructor. |
647 (** [[ | 653 (** [[ |
648 ============================ | 654 ============================ |
649 even (n0 + m) | 655 even (n0 + m) |
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]. *) | 758 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]. *) |
753 | 759 |
754 SearchRewrite (_ + S _). | 760 SearchRewrite (_ + S _). |
755 (** %\vspace{-.15in}% [[ | 761 (** %\vspace{-.15in}% [[ |
756 plus_n_Sm : forall n m : nat, S (n + m) = n + S m | 762 plus_n_Sm : forall n m : nat, S (n + m) = n + S m |
757 ]] *) | 763 ]] |
764 *) | |
758 | 765 |
759 rewrite <- plus_n_Sm in H0. | 766 rewrite <- plus_n_Sm in H0. |
760 | 767 |
761 (** The induction hypothesis lets us complete the proof. *) | 768 (** The induction hypothesis lets us complete the proof. *) |
762 | 769 |
917 %\item%#<li># If you follow the last hint, you may find yourself writing a proof that involves an expression with [eq_nat_dec] that you would like to simplify. Running [destruct] on the particular call to [eq_nat_dec] should do the trick. You can automate this advice with a piece of Ltac: [[ | 924 %\item%#<li># If you follow the last hint, you may find yourself writing a proof that involves an expression with [eq_nat_dec] that you would like to simplify. Running [destruct] on the particular call to [eq_nat_dec] should do the trick. You can automate this advice with a piece of Ltac: [[ |
918 | 925 |
919 match goal with | 926 match goal with |
920 | [ |- context[eq_nat_dec ?X ?Y] ] => destruct (eq_nat_dec X Y) | 927 | [ |- context[eq_nat_dec ?X ?Y] ] => destruct (eq_nat_dec X Y) |
921 end | 928 end |
922 ]] #</li># | 929 ]] |
930 #</li># | |
923 %\item%#<li># You probably do not want to use an inductive definition for compatibility of variable assignments and typings.#</li># | 931 %\item%#<li># You probably do not want to use an inductive definition for compatibility of variable assignments and typings.#</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># | 932 %\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># |
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># | 933 %\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># |
926 #</ol> </li>#%\end{enumerate}% | 934 #</ol> </li>#%\end{enumerate}% |
927 | 935 |