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. *)