Mercurial > cpdt > repo
comparison src/Subset.v @ 440:f923024bd284
Vertical spacing pass, through end of Subset
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Mon, 30 Jul 2012 16:50:02 -0400 |
parents | 393b8ed99c2f |
children | 89c67796754e |
comparison
equal
deleted
inserted
replaced
439:393b8ed99c2f | 440:f923024bd284 |
---|---|
81 | 81 |
82 Eval compute in pred_strong1 two_gt0. | 82 Eval compute in pred_strong1 two_gt0. |
83 (** %\vspace{-.15in}% [[ | 83 (** %\vspace{-.15in}% [[ |
84 = 1 | 84 = 1 |
85 : nat | 85 : nat |
86 | |
87 ]] | 86 ]] |
88 | 87 |
89 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. | 88 %\smallskip{}%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. |
90 | 89 |
91 [[ | 90 %\vspace{-.15in}%[[ |
92 Definition pred_strong1' (n : nat) (pf : n > 0) : nat := | 91 Definition pred_strong1' (n : nat) (pf : n > 0) : nat := |
93 match n with | 92 match n with |
94 | O => match zgtz pf with end | 93 | O => match zgtz pf with end |
95 | S n' => n' | 94 | S n' => n' |
96 end. | 95 end. |
150 | 149 |
151 Print sig. | 150 Print sig. |
152 (** %\vspace{-.15in}% [[ | 151 (** %\vspace{-.15in}% [[ |
153 Inductive sig (A : Type) (P : A -> Prop) : Type := | 152 Inductive sig (A : Type) (P : A -> Prop) : Type := |
154 exist : forall x : A, P x -> sig P | 153 exist : forall x : A, P x -> sig P |
155 | |
156 ]] | 154 ]] |
157 | 155 |
158 The family [sig] is a Curry-Howard twin of [ex], except that [sig] is in [Type], while [ex] is in [Prop]. That means that [sig] values can survive extraction, while [ex] proofs will always be erased. The actual details of extraction of [sig]s are more subtle, as we will see shortly. | 156 %\smallskip{}%The family [sig] is a Curry-Howard twin of [ex], except that [sig] is in [Type], while [ex] is in [Prop]. That means that [sig] values can survive extraction, while [ex] proofs will always be erased. The actual details of extraction of [sig]s are more subtle, as we will see shortly. |
159 | 157 |
160 We rewrite [pred_strong1], using some syntactic sugar for subset types. *) | 158 We rewrite [pred_strong1], using some syntactic sugar for subset types. *) |
161 | 159 |
162 Locate "{ _ : _ | _ }". | 160 Locate "{ _ : _ | _ }". |
163 (** %\vspace{-.15in}% [[ | 161 (** %\vspace{-.15in}% [[ |
299 | S n' => | 297 | S n' => |
300 fun _ : S n' > 0 => | 298 fun _ : S n' > 0 => |
301 exist (fun m : nat => S n' = S m) n' (eq_refl (S n')) | 299 exist (fun m : nat => S n' = S m) n' (eq_refl (S n')) |
302 end | 300 end |
303 : forall n : nat, n > 0 -> {m : nat | n = S m} | 301 : forall n : nat, n > 0 -> {m : nat | n = S m} |
304 | |
305 ]] | 302 ]] |
306 | 303 |
307 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. *) | 304 %\smallskip{}%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. *) |
308 | 305 |
309 Eval compute in pred_strong4 two_gt0. | 306 Eval compute in pred_strong4 two_gt0. |
310 (** %\vspace{-.15in}% [[ | 307 (** %\vspace{-.15in}% [[ |
311 = exist (fun m : nat => 2 = S m) 1 (eq_refl 2) | 308 = exist (fun m : nat => 2 = S m) 1 (eq_refl 2) |
312 : {m : nat | 2 = S m} | 309 : {m : nat | 2 = S m} |
313 ]] | 310 ]] |
314 | 311 |
315 A tactic modifier called %\index{tactics!abstract}%[abstract] can be helpful for producing shorter terms, by automatically abstracting subgoals into named lemmas. *) | 312 %\smallskip{}%A tactic modifier called %\index{tactics!abstract}%[abstract] can be helpful for producing shorter terms, by automatically abstracting subgoals into named lemmas. *) |
316 | 313 |
317 (* begin thide *) | 314 (* begin thide *) |
318 Definition pred_strong4' : forall n : nat, n > 0 -> {m : nat | n = S m}. | 315 Definition pred_strong4' : forall n : nat, n > 0 -> {m : nat | n = S m}. |
319 refine (fun n => | 316 refine (fun n => |
320 match n with | 317 match n with |
359 (** %\vspace{-.15in}% [[ | 356 (** %\vspace{-.15in}% [[ |
360 = [1] | 357 = [1] |
361 : {m : nat | 2 = S m} | 358 : {m : nat | 2 = S m} |
362 ]] | 359 ]] |
363 | 360 |
364 One other alternative is worth demonstrating. Recent Coq versions include a facility called %\index{Program}%[Program] that streamlines this style of definition. Here is a complete implementation using [Program].%\index{Vernacular commands!Obligation Tactic}\index{Vernacular commands!Program Definition}% *) | 361 %\smallskip{}%One other alternative is worth demonstrating. Recent Coq versions include a facility called %\index{Program}%[Program] that streamlines this style of definition. Here is a complete implementation using [Program].%\index{Vernacular commands!Obligation Tactic}\index{Vernacular commands!Program Definition}% *) |
365 | 362 |
366 Obligation Tactic := crush. | 363 Obligation Tactic := crush. |
367 | 364 |
368 Program Definition pred_strong6 (n : nat) (_ : n > 0) : {m : nat | n = S m} := | 365 Program Definition pred_strong6 (n : nat) (_ : n > 0) : {m : nat | n = S m} := |
369 match n with | 366 match n with |
377 (** %\vspace{-.15in}% [[ | 374 (** %\vspace{-.15in}% [[ |
378 = [1] | 375 = [1] |
379 : {m : nat | 2 = S m} | 376 : {m : nat | 2 = S m} |
380 ]] | 377 ]] |
381 | 378 |
382 In this case, we see that the new definition yields the same computational behavior as before. *) | 379 %\smallskip{}%In this case, we see that the new definition yields the same computational behavior as before. *) |
383 | 380 |
384 | 381 |
385 (** * Decidable Proposition Types *) | 382 (** * Decidable Proposition Types *) |
386 | 383 |
387 (** There is another type in the standard library which captures the idea of program values that indicate which of two propositions is true.%\index{Gallina terms!sumbool}% *) | 384 (** There is another type in the standard library which captures the idea of program values that indicate which of two propositions is true.%\index{Gallina terms!sumbool}% *) |
421 Eval compute in eq_nat_dec 2 3. | 418 Eval compute in eq_nat_dec 2 3. |
422 (** %\vspace{-.15in}% [[ | 419 (** %\vspace{-.15in}% [[ |
423 = No | 420 = No |
424 : {2 = 3} + {2 <> 3} | 421 : {2 = 3} + {2 <> 3} |
425 ]] | 422 ]] |
426 *) | 423 |
427 | 424 %\smallskip{}%Note that the %\coqdocnotation{%#<tt>#Yes#</tt>#%}% and %\coqdocnotation{%#<tt>#No#</tt>#%}% notations are hiding proofs establishing the correctness of the outputs. |
428 (** Note that the %\coqdocnotation{%#<tt>#Yes#</tt>#%}% and %\coqdocnotation{%#<tt>#No#</tt>#%}% notations are hiding proofs establishing the correctness of the outputs. | |
429 | 425 |
430 Our definition extracts to reasonable OCaml code. *) | 426 Our definition extracts to reasonable OCaml code. *) |
431 | 427 |
432 Extraction eq_nat_dec. | 428 Extraction eq_nat_dec. |
433 | 429 |
530 Eval compute in In_dec eq_nat_dec 3 (1 :: 2 :: nil). | 526 Eval compute in In_dec eq_nat_dec 3 (1 :: 2 :: nil). |
531 (** %\vspace{-.15in}% [[ | 527 (** %\vspace{-.15in}% [[ |
532 = No | 528 = No |
533 : {In 3 (1 :: 2 :: nil)} + {~ In 3 (1 :: 2 :: nil)} | 529 : {In 3 (1 :: 2 :: nil)} + {~ In 3 (1 :: 2 :: nil)} |
534 ]] | 530 ]] |
535 *) | 531 |
536 | 532 %\smallskip{}%[In_dec] has a reasonable extraction to OCaml. *) |
537 (** [In_dec] has a reasonable extraction to OCaml. *) | |
538 | 533 |
539 Extraction In_dec. | 534 Extraction In_dec. |
540 (* end thide *) | 535 (* end thide *) |
541 | 536 |
542 (** %\begin{verbatim} | 537 (** %\begin{verbatim} |
599 (** %\vspace{-.15in}% [[ | 594 (** %\vspace{-.15in}% [[ |
600 = ?? | 595 = ?? |
601 : {{m | 0 = S m}} | 596 : {{m | 0 = S m}} |
602 ]] | 597 ]] |
603 | 598 |
604 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 %\index{Gallina terms!sumor}%[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]. *) | 599 %\smallskip{}%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 %\index{Gallina terms!sumor}%[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]. *) |
605 | 600 |
606 Print sumor. | 601 Print sumor. |
607 (** %\vspace{-.15in}% [[ | 602 (** %\vspace{-.15in}% [[ |
608 Inductive sumor (A : Type) (B : Prop) : Type := | 603 Inductive sumor (A : Type) (B : Prop) : Type := |
609 inleft : A -> A + {B} | inright : B -> A + {B} | 604 inleft : A -> A + {B} | inright : B -> A + {B} |
610 ]] | 605 ]] |
611 *) | 606 |
612 | 607 %\smallskip{}%We add notations for easy use of the [sumor] constructors. The second notation is specialized to [sumor]s whose [A] parameters are instantiated with regular subset types, since this is how we will use [sumor] below. *) |
613 (** We add notations for easy use of the [sumor] constructors. The second notation is specialized to [sumor]s whose [A] parameters are instantiated with regular subset types, since this is how we will use [sumor] below. *) | |
614 | 608 |
615 Notation "!!" := (inright _ _). | 609 Notation "!!" := (inright _ _). |
616 Notation "[|| x ||]" := (inleft _ [x]). | 610 Notation "[|| x ||]" := (inleft _ [x]). |
617 | 611 |
618 (** Now we are ready to give the final version of possibly failing predecessor. The [sumor]-based type that we use is maximally expressive; any implementation of the type has the same input-output behavior. *) | 612 (** Now we are ready to give the final version of possibly failing predecessor. The [sumor]-based type that we use is maximally expressive; any implementation of the type has the same input-output behavior. *) |
779 Eval simpl in typeCheck (Plus (Nat 1) (Bool false)). | 773 Eval simpl in typeCheck (Plus (Nat 1) (Bool false)). |
780 (** %\vspace{-.15in}% [[ | 774 (** %\vspace{-.15in}% [[ |
781 = ?? | 775 = ?? |
782 : {{t | hasType (Plus (Nat 1) (Bool false)) t}} | 776 : {{t | hasType (Plus (Nat 1) (Bool false)) t}} |
783 ]] | 777 ]] |
784 *) | 778 |
785 | 779 %\smallskip{}%The type checker also extracts to some reasonable OCaml code. *) |
786 (** The type checker also extracts to some reasonable OCaml code. *) | |
787 | 780 |
788 Extraction typeCheck. | 781 Extraction typeCheck. |
789 | 782 |
790 (** %\begin{verbatim} | 783 (** %\begin{verbatim} |
791 (** val typeCheck : exp -> type0 maybe **) | 784 (** val typeCheck : exp -> type0 maybe **) |
934 = !! | 927 = !! |
935 : {t : type | hasType (Plus (Nat 1) (Bool false)) t} + | 928 : {t : type | hasType (Plus (Nat 1) (Bool false)) t} + |
936 {(forall t : type, ~ hasType (Plus (Nat 1) (Bool false)) t)} | 929 {(forall t : type, ~ hasType (Plus (Nat 1) (Bool false)) t)} |
937 ]] | 930 ]] |
938 | 931 |
939 The results of simplifying calls to [typeCheck'] look deceptively similar to the results for [typeCheck], but now the types of the results provide more information. *) | 932 %\smallskip{}%The results of simplifying calls to [typeCheck'] look deceptively similar to the results for [typeCheck], but now the types of the results provide more information. *) |