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