comparison src/Reflection.v @ 461:b6c47e6d43dc

Proofreading pass through Chapter 15
author Adam Chlipala <adam@chlipala.net>
date Wed, 29 Aug 2012 15:36:06 -0400
parents 0650420c127b
children 40a9a36844d6
comparison
equal deleted inserted replaced
460:38549f152568 461:b6c47e6d43dc
83 | 1 => No 83 | 1 => No
84 | S (S n') => Reduce (F n') 84 | S (S n') => Reduce (F n')
85 end); auto. 85 end); auto.
86 Defined. 86 Defined.
87 87
88 (** The function [check_even] may be viewed as a _verified decision procedure_, because its type guarantees that it never returns [Yes] for inputs that are not even. 88 (** The function [check_even] may be viewed as a _verified decision procedure_, because its type guarantees that it never returns %\coqdocnotation{%#<tt>#Yes#</tt>#%}% for inputs that are not even.
89 89
90 Now we can use dependent pattern-matching to write a function that performs a surprising feat. When given a [partial P], this function [partialOut] returns a proof of [P] if the [partial] value contains a proof, and it returns a (useless) proof of [True] otherwise. From the standpoint of ML and Haskell programming, it seems impossible to write such a type, but it is trivial with a [return] annotation. *) 90 Now we can use dependent pattern-matching to write a function that performs a surprising feat. When given a [partial P], this function [partialOut] returns a proof of [P] if the [partial] value contains a proof, and it returns a (useless) proof of [True] otherwise. From the standpoint of ML and Haskell programming, it seems impossible to write such a type, but it is trivial with a [return] annotation. *)
91 91
92 Definition partialOut (P : Prop) (x : [P]) := 92 Definition partialOut (P : Prop) (x : [P]) :=
93 match x return (match x with 93 match x return (match x with
143 | Yes => isEven 255 143 | Yes => isEven 255
144 | No => True 144 | No => True
145 end" while it is expected to have type "isEven 255" 145 end" while it is expected to have type "isEven 255"
146 >> 146 >>
147 147
148 As usual, the type checker performs no reductions to simplify error messages. If we reduced the first term ourselves, we would see that [check_even 255] reduces to a [No], so that the first term is equivalent to [True], which certainly does not unify with [isEven 255]. *) 148 As usual, the type checker performs no reductions to simplify error messages. If we reduced the first term ourselves, we would see that [check_even 255] reduces to a %\coqdocnotation{%#<tt>#No#</tt>#%}%, so that the first term is equivalent to [True], which certainly does not unify with [isEven 255]. *)
149 149
150 Abort. 150 Abort.
151 151
152 (** Our tactic [prove_even_reflective] is reflective because it performs a proof search process (a trivial one, in this case) wholly within Gallina, where the only use of Ltac is to translate a goal into an appropriate use of [check_even]. *) 152 (** Our tactic [prove_even_reflective] is reflective because it performs a proof search process (a trivial one, in this case) wholly within Gallina, where the only use of Ltac is to translate a goal into an appropriate use of [check_even]. *)
153 153
218 let t1 := tautReify P1 in 218 let t1 := tautReify P1 in
219 let t2 := tautReify P2 in 219 let t2 := tautReify P2 in
220 constr:(TautImp t1 t2) 220 constr:(TautImp t1 t2)
221 end. 221 end.
222 222
223 (** With [tautReify] available, it is easy to finish our reflective tactic. We look at the goal formula, reflect it, and apply [tautTrue] to the reflected formula. *) 223 (** With [tautReify] available, it is easy to finish our reflective tactic. We look at the goal formula, reify it, and apply [tautTrue] to the reified formula. *)
224 224
225 Ltac obvious := 225 Ltac obvious :=
226 match goal with 226 match goal with
227 | [ |- ?P ] => 227 | [ |- ?P ] =>
228 let t := tautReify P in 228 let t := tautReify P in
299 | Ident => nil 299 | Ident => nil
300 | Var x => x :: nil 300 | Var x => x :: nil
301 | Op me1 me2 => flatten me1 ++ flatten me2 301 | Op me1 me2 => flatten me1 ++ flatten me2
302 end. 302 end.
303 303
304 (** [flatten] has a straightforward correctness proof in terms of our [denote] functions. *) 304 (** This function has a straightforward correctness proof in terms of our [denote] functions. *)
305 305
306 Lemma flatten_correct' : forall ml2 ml1, 306 Lemma flatten_correct' : forall ml2 ml1,
307 mldenote ml1 + mldenote ml2 = mldenote (ml1 ++ ml2). 307 mldenote ml1 + mldenote ml2 = mldenote (ml1 ++ ml2).
308 induction ml1; crush. 308 induction ml1; crush.
309 Qed. 309 Qed.
420 | Or f1 f2 => formulaDenote atomics f1 \/ formulaDenote atomics f2 420 | Or f1 f2 => formulaDenote atomics f1 \/ formulaDenote atomics f2
421 | Imp f1 f2 => formulaDenote atomics f1 --> formulaDenote atomics f2 421 | Imp f1 f2 => formulaDenote atomics f1 --> formulaDenote atomics f2
422 end. 422 end.
423 (* end thide *) 423 (* end thide *)
424 424
425 (** The %\index{Gallina terms!varmap}%[varmap] type family implements maps from [index] values. In this case, we define an assignment as a map from variables to [Prop]s. Our reifier [formulaDenote] works with an assignment, and we use the [varmap_find] function to consult the assignment in the [Atomic] case. The first argument to [varmap_find] is a default value, in case the variable is not found. *) 425 (** The %\index{Gallina terms!varmap}%[varmap] type family implements maps from [index] values. In this case, we define an assignment as a map from variables to [Prop]s. Our interpretation function [formulaDenote] works with an assignment, and we use the [varmap_find] function to consult the assignment in the [Atomic] case. The first argument to [varmap_find] is a default value, in case the variable is not found. *)
426 426
427 Section my_tauto. 427 Section my_tauto.
428 Variable atomics : asgn. 428 Variable atomics : asgn.
429 429
430 Definition holds (v : index) := varmap_find False v atomics. 430 Definition holds (v : index) := varmap_find False v atomics.
699 | (_, ?xs') => 699 | (_, ?xs') =>
700 let n := lookup x xs' in 700 let n := lookup x xs' in
701 constr:(S n) 701 constr:(S n)
702 end. 702 end.
703 703
704 (** The next building block is a procedure for reifying a term, given a list of all allowed variable values. We are free to make this procedure partial, where tactic failure may be triggered upon attempting to reflect a term containing subterms not included in the list of variables. The output type of the term is a copy of [formula] where [index] is replaced by [nat], in the type of the constructor for atomic formulas. *) 704 (** The next building block is a procedure for reifying a term, given a list of all allowed variable values. We are free to make this procedure partial, where tactic failure may be triggered upon attempting to reify a term containing subterms not included in the list of variables. The type of the output term is a copy of [formula] where [index] is replaced by [nat], in the type of the constructor for atomic formulas. *)
705 705
706 Inductive formula' : Set := 706 Inductive formula' : Set :=
707 | Atomic' : nat -> formula' 707 | Atomic' : nat -> formula'
708 | Truth' : formula' 708 | Truth' : formula'
709 | Falsehood' : formula' 709 | Falsehood' : formula'
866 ]] 866 ]]
867 *) 867 *)
868 868
869 Abort. 869 Abort.
870 870
871 (** Our encoding here uses Coq functions to represent binding within the terms we reify, which makes it difficult to implement certain functions over reified terms. An alternative would be to represent variables with numbers. This can be done by writing a slightly smarter reification function that detects variable references by detecting when term arguments are just compositions of [fst] and [snd]; from the order of the compositions we may read off the variable number. We leave the details as an exercise for the reader. *) 871 (** Our encoding here uses Coq functions to represent binding within the terms we reify, which makes it difficult to implement certain functions over reified terms. An alternative would be to represent variables with numbers. This can be done by writing a slightly smarter reification function that identifies variable references by detecting when term arguments are just compositions of [fst] and [snd]; from the order of the compositions we may read off the variable number. We leave the details as an exercise for the reader. *)