Mercurial > cpdt > repo
comparison src/Subset.v @ 282:caa69851c78d
Subset suggestions from PC; improvements to build process for coqdoc fontification
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 05 Nov 2010 10:35:56 -0400 |
parents | aa3c054afce0 |
children | 2c88fc1dbe33 |
comparison
equal
deleted
inserted
replaced
281:4146889930c5 | 282:caa69851c78d |
---|---|
1 (* Copyright (c) 2008-2009, Adam Chlipala | 1 (* Copyright (c) 2008-2010, Adam Chlipala |
2 * | 2 * |
3 * This work is licensed under a | 3 * This work is licensed under a |
4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 | 4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 |
5 * Unported License. | 5 * Unported License. |
6 * The license text is available at: | 6 * The license text is available at: |
69 | S n' => fun _ => n' | 69 | S n' => fun _ => n' |
70 end. | 70 end. |
71 | 71 |
72 (** We expand the type of [pred] to include a %\textit{%#<i>#proof#</i>#%}% that its argument [n] is greater than 0. When [n] is 0, we use the proof to derive a contradiction, which we can use to build a value of any type via a vacuous pattern match. When [n] is a successor, we have no need for the proof and just return the answer. The proof argument can be said to have a %\textit{%#<i>#dependent#</i>#%}% type, because its type depends on the %\textit{%#<i>#value#</i>#%}% of the argument [n]. | 72 (** We expand the type of [pred] to include a %\textit{%#<i>#proof#</i>#%}% that its argument [n] is greater than 0. When [n] is 0, we use the proof to derive a contradiction, which we can use to build a value of any type via a vacuous pattern match. When [n] is a successor, we have no need for the proof and just return the answer. The proof argument can be said to have a %\textit{%#<i>#dependent#</i>#%}% type, because its type depends on the %\textit{%#<i>#value#</i>#%}% of the argument [n]. |
73 | 73 |
74 One aspect in particular of the definition of [pred_strong1] may be surprising. We took advantage of [Definition]'s syntactic sugar for defining function arguments in the case of [n], but we bound the proofs later with explicit [fun] expressions. Let us see what happens if we write this function in the way that at first seems most natural. | 74 Coq's [Eval] command can execute particular invocations of [pred_strong1] just as easily as it can execute more traditional functional programs. Note that Coq has decided that argument [n] of [pred_strong1] can be made %\textit{%#<i>#implicit#</i>#%}%, since it can be deduced from the type of the second argument, so we need not write [n] in function calls. *) |
75 | |
76 Theorem two_gt0 : 2 > 0. | |
77 crush. | |
78 Qed. | |
79 | |
80 Eval compute in pred_strong1 two_gt0. | |
81 (** %\vspace{-.15in}% [[ | |
82 = 1 | |
83 : nat | |
84 | |
85 ]] | |
86 | |
87 One aspect in particular of the definition of [pred_strong1] may be surprising. We took advantage of [Definition]'s syntactic sugar for defining function arguments in the case of [n], but we bound the proofs later with explicit [fun] expressions. Let us see what happens if we write this function in the way that at first seems most natural. | |
75 | 88 |
76 [[ | 89 [[ |
77 Definition pred_strong1' (n : nat) (pf : n > 0) : nat := | 90 Definition pred_strong1' (n : nat) (pf : n > 0) : nat := |
78 match n with | 91 match n with |
79 | O => match zgtz pf with end | 92 | O => match zgtz pf with end |
143 match s with | 156 match s with |
144 | exist O pf => match zgtz pf with end | 157 | exist O pf => match zgtz pf with end |
145 | exist (S n') _ => n' | 158 | exist (S n') _ => n' |
146 end. | 159 end. |
147 | 160 |
161 (** To build a value of a subset type, we use the [exist] constructor, and the details of how to do that follow from the output of our earlier [Print sig] command. *) | |
162 | |
163 Eval compute in pred_strong2 (exist _ 2 two_gt0). | |
164 (** %\vspace{-.15in}% [[ | |
165 = 1 | |
166 : nat | |
167 | |
168 ]] *) | |
169 | |
148 Extraction pred_strong2. | 170 Extraction pred_strong2. |
149 | 171 |
150 (** %\begin{verbatim} | 172 (** %\begin{verbatim} |
151 (** val pred_strong2 : nat -> nat **) | 173 (** val pred_strong2 : nat -> nat **) |
152 | 174 |
171 match s return {m : nat | proj1_sig s = S m} with | 193 match s return {m : nat | proj1_sig s = S m} with |
172 | exist 0 pf => match zgtz pf with end | 194 | exist 0 pf => match zgtz pf with end |
173 | exist (S n') pf => exist _ n' (refl_equal _) | 195 | exist (S n') pf => exist _ n' (refl_equal _) |
174 end. | 196 end. |
175 | 197 |
176 (** The function [proj1_sig] extracts the base value from a subset type. Besides the use of that function, the only other new thing is the use of the [exist] constructor to build a new [sig] value, and the details of how to do that follow from the output of our earlier [Print] command. It also turns out that we need to include an explicit [return] clause here, since Coq's heuristics are not smart enough to propagate the result type that we wrote earlier. | 198 Eval compute in pred_strong3 (exist _ 2 two_gt0). |
199 (** %\vspace{-.15in}% [[ | |
200 = exist (fun m : nat => 2 = S m) 1 (refl_equal 2) | |
201 : {m : nat | proj1_sig (exist (lt 0) 2 two_gt0) = S m} | |
202 | |
203 ]] *) | |
204 | |
205 (** The function [proj1_sig] extracts the base value from a subset type. It turns out that we need to include an explicit [return] clause here, since Coq's heuristics are not smart enough to propagate the result type that we wrote earlier. | |
177 | 206 |
178 By now, the reader is probably ready to believe that the new [pred_strong] leads to the same OCaml code as we have seen several times so far, and Coq does not disappoint. *) | 207 By now, the reader is probably ready to believe that the new [pred_strong] leads to the same OCaml code as we have seen several times so far, and Coq does not disappoint. *) |
179 | 208 |
180 Extraction pred_strong3. | 209 Extraction pred_strong3. |
181 | 210 |
251 end | 280 end |
252 : forall n : nat, n > 0 -> {m : nat | n = S m} | 281 : forall n : nat, n > 0 -> {m : nat | n = S m} |
253 | 282 |
254 ]] | 283 ]] |
255 | 284 |
256 We see the code we entered, with some proofs filled in. The first proof obligation, the second argument to [False_rec], is filled in with a nasty-looking proof term that we can be glad we did not enter by hand. The second proof obligation is a simple reflexivity proof. | 285 We see the code we entered, with some proofs filled in. The first proof obligation, the second argument to [False_rec], is filled in with a nasty-looking proof term that we can be glad we did not enter by hand. The second proof obligation is a simple reflexivity proof. *) |
257 | 286 |
258 We are almost done with the ideal implementation of dependent predecessor. We can use Coq's syntax extension facility to arrive at code with almost no complexity beyond a Haskell or ML program with a complete specification in a comment. *) | 287 Eval compute in pred_strong4 two_gt0. |
288 (** %\vspace{-.15in}% [[ | |
289 = exist (fun m : nat => 2 = S m) 1 (refl_equal 2) | |
290 : {m : nat | 2 = S m} | |
291 | |
292 ]] | |
293 | |
294 We are almost done with the ideal implementation of dependent predecessor. We can use Coq's syntax extension facility to arrive at code with almost no complexity beyond a Haskell or ML program with a complete specification in a comment. *) | |
259 | 295 |
260 Notation "!" := (False_rec _ _). | 296 Notation "!" := (False_rec _ _). |
261 Notation "[ e ]" := (exist _ e _). | 297 Notation "[ e ]" := (exist _ e _). |
262 | 298 |
263 Definition pred_strong5 (n : nat) : n > 0 -> {m : nat | n = S m}. | 299 Definition pred_strong5 (n : nat) : n > 0 -> {m : nat | n = S m}. |
266 | O => fun _ => ! | 302 | O => fun _ => ! |
267 | S n' => fun _ => [n'] | 303 | S n' => fun _ => [n'] |
268 end); crush. | 304 end); crush. |
269 Defined. | 305 Defined. |
270 | 306 |
271 (** One other alternative is worth demonstrating. Recent Coq versions include a facility called [Program] that streamlines this style of definition. Here is a complete implementation using [Program]. *) | 307 (** By default, notations are also used in pretty-printing terms, including results of evaluation. *) |
308 | |
309 Eval compute in pred_strong5 two_gt0. | |
310 (** %\vspace{-.15in}% [[ | |
311 = [1] | |
312 : {m : nat | 2 = S m} | |
313 | |
314 ]] | |
315 | |
316 One other alternative is worth demonstrating. Recent Coq versions include a facility called [Program] that streamlines this style of definition. Here is a complete implementation using [Program]. *) | |
272 | 317 |
273 Obligation Tactic := crush. | 318 Obligation Tactic := crush. |
274 | 319 |
275 Program Definition pred_strong6 (n : nat) (_ : n > 0) : {m : nat | n = S m} := | 320 Program Definition pred_strong6 (n : nat) (_ : n > 0) : {m : nat | n = S m} := |
276 match n with | 321 match n with |
277 | O => _ | 322 | O => _ |
278 | S n' => n' | 323 | S n' => n' |
279 end. | 324 end. |
280 | 325 |
281 (** Printing the resulting definition of [pred_strong6] yields a term very similar to what we built with [refine]. [Program] can save time in writing programs that use subset types. Nonetheless, [refine] is often just as effective, and [refine] gives you more control over the form the final term takes, which can be useful when you want to prove additional theorems about your definition. [Program] will sometimes insert type casts that can complicate theorem-proving. *) | 326 (** Printing the resulting definition of [pred_strong6] yields a term very similar to what we built with [refine]. [Program] can save time in writing programs that use subset types. Nonetheless, [refine] is often just as effective, and [refine] gives you more control over the form the final term takes, which can be useful when you want to prove additional theorems about your definition. [Program] will sometimes insert type casts that can complicate theorem-proving. *) |
327 | |
328 Eval compute in pred_strong6 two_gt0. | |
329 (** %\vspace{-.15in}% [[ | |
330 = [1] | |
331 : {m : nat | 2 = S m} | |
332 | |
333 ]] *) | |
282 | 334 |
283 | 335 |
284 (** * Decidable Proposition Types *) | 336 (** * Decidable Proposition Types *) |
285 | 337 |
286 (** There is another type in the standard library which captures the idea of program values that indicate which of two propositions is true. *) | 338 (** There is another type in the standard library which captures the idea of program values that indicate which of two propositions is true. *) |
310 | O, O => Yes | 362 | O, O => Yes |
311 | S n', S m' => Reduce (f n' m') | 363 | S n', S m' => Reduce (f n' m') |
312 | _, _ => No | 364 | _, _ => No |
313 end); congruence. | 365 end); congruence. |
314 Defined. | 366 Defined. |
367 | |
368 Eval compute in eq_nat_dec 2 2. | |
369 (** %\vspace{-.15in}% [[ | |
370 = Yes | |
371 : {2 = 2} + {2 <> 2} | |
372 | |
373 ]] *) | |
374 | |
375 Eval compute in eq_nat_dec 2 3. | |
376 (** %\vspace{-.15in}% [[ | |
377 = No | |
378 : {2 = 2} + {2 <> 2} | |
379 | |
380 ]] *) | |
315 | 381 |
316 (** Our definition extracts to reasonable OCaml code. *) | 382 (** Our definition extracts to reasonable OCaml code. *) |
317 | 383 |
318 Extraction eq_nat_dec. | 384 Extraction eq_nat_dec. |
319 | 385 |
399 refine (fix f (x : A) (ls : list A) : {In x ls} + {~ In x ls} := | 465 refine (fix f (x : A) (ls : list A) : {In x ls} + {~ In x ls} := |
400 match ls with | 466 match ls with |
401 | nil => No | 467 | nil => No |
402 | x' :: ls' => A_eq_dec x x' || f x ls' | 468 | x' :: ls' => A_eq_dec x x' || f x ls' |
403 end); crush. | 469 end); crush. |
404 Qed. | 470 Defined. |
405 End In_dec. | 471 End In_dec. |
472 | |
473 Eval compute in In_dec eq_nat_dec 2 (1 :: 2 :: nil). | |
474 (** %\vspace{-.15in}% [[ | |
475 = Yes | |
476 : {In 2 (1 :: 2 :: nil)} + {~ In 2 (1 :: 2 :: nil)} | |
477 | |
478 ]] *) | |
479 | |
480 Eval compute in In_dec eq_nat_dec 3 (1 :: 2 :: nil). | |
481 (** %\vspace{-.15in}% [[ | |
482 = No | |
483 : {In 3 (1 :: 2 :: nil)} + {~ In 3 (1 :: 2 :: nil)} | |
484 | |
485 ]] *) | |
406 | 486 |
407 (** [In_dec] has a reasonable extraction to OCaml. *) | 487 (** [In_dec] has a reasonable extraction to OCaml. *) |
408 | 488 |
409 Extraction In_dec. | 489 Extraction In_dec. |
410 (* end thide *) | 490 (* end thide *) |
454 | O => ?? | 534 | O => ?? |
455 | S n' => [[n']] | 535 | S n' => [[n']] |
456 end); trivial. | 536 end); trivial. |
457 Defined. | 537 Defined. |
458 | 538 |
459 (** Because we used [maybe], one valid implementation of the type we gave [pred_strong7] would return [??] in every case. We can strengthen the type to rule out such vacuous implementations, and the type family [sumor] from the standard library provides the easiest starting point. For type [A] and proposition [B], [A + {B}] desugars to [sumor A B], whose values are either values of [A] or proofs of [B]. *) | 539 Eval compute in pred_strong7 2. |
540 (** %\vspace{-.15in}% [[ | |
541 = [[1]] | |
542 : {{m | 2 = S m}} | |
543 | |
544 ]] *) | |
545 | |
546 Eval compute in pred_strong7 0. | |
547 (** %\vspace{-.15in}% [[ | |
548 = ?? | |
549 : {{m | 0 = S m}} | |
550 | |
551 ]] | |
552 | |
553 Because we used [maybe], one valid implementation of the type we gave [pred_strong7] would return [??] in every case. We can strengthen the type to rule out such vacuous implementations, and the type family [sumor] from the standard library provides the easiest starting point. For type [A] and proposition [B], [A + {B}] desugars to [sumor A B], whose values are either values of [A] or proofs of [B]. *) | |
460 | 554 |
461 Print sumor. | 555 Print sumor. |
462 (** %\vspace{-.15in}% [[ | 556 (** %\vspace{-.15in}% [[ |
463 Inductive sumor (A : Type) (B : Prop) : Type := | 557 Inductive sumor (A : Type) (B : Prop) : Type := |
464 inleft : A -> A + {B} | inright : B -> A + {B} | 558 inleft : A -> A + {B} | inright : B -> A + {B} |
478 match n with | 572 match n with |
479 | O => !! | 573 | O => !! |
480 | S n' => [[[n']]] | 574 | S n' => [[[n']]] |
481 end); trivial. | 575 end); trivial. |
482 Defined. | 576 Defined. |
577 | |
578 Eval compute in pred_strong8 2. | |
579 (** %\vspace{-.15in}% [[ | |
580 = [[[1]]] | |
581 : {m : nat | 2 = S m} + {2 = 0} | |
582 | |
583 ]] *) | |
584 | |
585 Eval compute in pred_strong8 0. | |
586 (** %\vspace{-.15in}% [[ | |
587 = !! | |
588 : {m : nat | 0 = S m} + {0 = 0} | |
589 | |
590 ]] *) | |
483 | 591 |
484 | 592 |
485 (** * Monadic Notations *) | 593 (** * Monadic Notations *) |
486 | 594 |
487 (** We can treat [maybe] like a monad, in the same way that the Haskell [Maybe] type is interpreted as a failure monad. Our [maybe] has the wrong type to be a literal monad, but a "bind"-like notation will still be helpful. *) | 595 (** We can treat [maybe] like a monad, in the same way that the Haskell [Maybe] type is interpreted as a failure monad. Our [maybe] has the wrong type to be a literal monad, but a "bind"-like notation will still be helpful. *) |