comparison src/Subset.v @ 423:d3a40c044ab4

Pass through Subset, to incorporate new coqdoc features
author Adam Chlipala <adam@chlipala.net>
date Wed, 25 Jul 2012 17:03:33 -0400
parents 1edeec5d5d0c
children 5f25705a10ea
comparison
equal deleted inserted replaced
422:a730378789f5 423:d3a40c044ab4
20 20
21 (** %\part{Programming with Dependent Types} 21 (** %\part{Programming with Dependent Types}
22 22
23 \chapter{Subset Types and Variations}% *) 23 \chapter{Subset Types and Variations}% *)
24 24
25 (** So far, we have seen many examples of what we might call %``%#"#classical program verification.#"#%''% We write programs, write their specifications, and then prove that the programs satisfy their specifications. The programs that we have written in Coq have been normal functional programs that we could just as well have written in Haskell or ML. In this chapter, we start investigating uses of%\index{dependent types}% _dependent types_ to integrate programming, specification, and proving into a single phase. The techniques we will learn make it possible to reduce the cost of program verification dramatically. *) 25 (** So far, we have seen many examples of what we might call "classical program verification." We write programs, write their specifications, and then prove that the programs satisfy their specifications. The programs that we have written in Coq have been normal functional programs that we could just as well have written in Haskell or ML. In this chapter, we start investigating uses of%\index{dependent types}% _dependent types_ to integrate programming, specification, and proving into a single phase. The techniques we will learn make it possible to reduce the cost of program verification dramatically. *)
26 26
27 27
28 (** * Introducing Subset Types *) 28 (** * Introducing Subset Types *)
29 29
30 (** Let us consider several ways of implementing the natural number predecessor function. We start by displaying the definition from the standard library: *) 30 (** Let us consider several ways of implementing the natural number predecessor function. We start by displaying the definition from the standard library: *)
31
32 (* begin hide *)
33 Definition foo := pred.
34 (* end hide *)
31 35
32 Print pred. 36 Print pred.
33 (** %\vspace{-.15in}% [[ 37 (** %\vspace{-.15in}% [[
34 pred = fun n : nat => match n with 38 pred = fun n : nat => match n with
35 | 0 => 0 39 | 0 => 0
140 144
141 (** The proof argument has disappeared! We get exactly the OCaml code we would have written manually. This is our first demonstration of the main technically interesting feature of Coq program extraction: program components of type [Prop] are erased systematically. 145 (** The proof argument has disappeared! We get exactly the OCaml code we would have written manually. This is our first demonstration of the main technically interesting feature of Coq program extraction: program components of type [Prop] are erased systematically.
142 146
143 We can reimplement our dependently typed [pred] based on%\index{subset types}% _subset types_, defined in the standard library with the type family %\index{Gallina terms!sig}%[sig]. *) 147 We can reimplement our dependently typed [pred] based on%\index{subset types}% _subset types_, defined in the standard library with the type family %\index{Gallina terms!sig}%[sig]. *)
144 148
149 (* begin hide *)
150 Definition bar := (sig, ex).
151 (* end hide *)
152
145 Print sig. 153 Print sig.
146 (** %\vspace{-.15in}% [[ 154 (** %\vspace{-.15in}% [[
147 Inductive sig (A : Type) (P : A -> Prop) : Type := 155 Inductive sig (A : Type) (P : A -> Prop) : Type :=
148 exist : forall x : A, P x -> sig P 156 exist : forall x : A, P x -> sig P
149 157
207 (** %\vspace{-.15in}% [[ 215 (** %\vspace{-.15in}% [[
208 = exist (fun m : nat => 2 = S m) 1 (refl_equal 2) 216 = exist (fun m : nat => 2 = S m) 1 (refl_equal 2)
209 : {m : nat | proj1_sig (exist (lt 0) 2 two_gt0) = S m} 217 : {m : nat | proj1_sig (exist (lt 0) 2 two_gt0) = S m}
210 ]] 218 ]]
211 *) 219 *)
220
221 (* begin hide *)
222 Definition pred_strong := 0.
223 (* end hide *)
212 224
213 (** The function %\index{Gallina terms!proj1\_sig}%[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. 225 (** The function %\index{Gallina terms!proj1\_sig}%[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.
214 226
215 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. *) 227 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. *)
216 228
242 end). 254 end).
243 255
244 (* begin thide *) 256 (* begin thide *)
245 (** We build [pred_strong4] using tactic-based proving, beginning with a [Definition] command that ends in a period before a definition is given. Such a command enters the interactive proving mode, with the type given for the new identifier as our proof goal. It may seem strange to change perspective so implicitly between programming and proving, but recall that programs and proofs are two sides of the same coin in Coq, thanks to the Curry-Howard correspondence. 257 (** We build [pred_strong4] using tactic-based proving, beginning with a [Definition] command that ends in a period before a definition is given. Such a command enters the interactive proving mode, with the type given for the new identifier as our proof goal. It may seem strange to change perspective so implicitly between programming and proving, but recall that programs and proofs are two sides of the same coin in Coq, thanks to the Curry-Howard correspondence.
246 258
247 We do most of the work with the %\index{tactics!refine}%[refine] tactic, to which we pass a partial %``%#"#proof#"#%''% of the type we are trying to prove. There may be some pieces left to fill in, indicated by underscores. Any underscore that Coq cannot reconstruct with type inference is added as a proof subgoal. In this case, we have two subgoals: 259 We do most of the work with the %\index{tactics!refine}%[refine] tactic, to which we pass a partial "proof" of the type we are trying to prove. There may be some pieces left to fill in, indicated by underscores. Any underscore that Coq cannot reconstruct with type inference is added as a proof subgoal. In this case, we have two subgoals:
248 260
249 %\vspace{.1in} \noindent 2 \coqdockw{subgoals}\vspace{-.1in}%#<tt>2 subgoals</tt># 261 %\vspace{.1in} \noindent 2 \coqdockw{subgoals}\vspace{-.1in}%#<tt>2 subgoals</tt>#
250 [[ 262 [[
251 263
252 n : nat 264 n : nat
268 | S n' => fun _ => exist _ n' _ 280 | S n' => fun _ => exist _ n' _
269 end); crush. 281 end); crush.
270 (* end thide *) 282 (* end thide *)
271 Defined. 283 Defined.
272 284
273 (** We end the %``%#"#proof#"#%''% with %\index{Vernacular commands!Defined}%[Defined] instead of [Qed], so that the definition we constructed remains visible. This contrasts to the case of ending a proof with [Qed], where the details of the proof are hidden afterward. (More formally, [Defined] marks an identifier as%\index{transparent}% _transparent_, allowing it to be unfolded; while [Qed] marks an identifier as%\index{opaque}% _opaque_, preventing unfolding.) Let us see what our proof script constructed. *) 285 (** We end the "proof" with %\index{Vernacular commands!Defined}%[Defined] instead of [Qed], so that the definition we constructed remains visible. This contrasts to the case of ending a proof with [Qed], where the details of the proof are hidden afterward. (More formally, [Defined] marks an identifier as%\index{transparent}% _transparent_, allowing it to be unfolded; while [Qed] marks an identifier as%\index{opaque}% _opaque_, preventing unfolding.) Let us see what our proof script constructed. *)
274 286
275 Print pred_strong4. 287 Print pred_strong4.
276 (** %\vspace{-.15in}% [[ 288 (** %\vspace{-.15in}% [[
277 pred_strong4 = 289 pred_strong4 =
278 fun n : nat => 290 fun n : nat =>
372 384
373 (** * Decidable Proposition Types *) 385 (** * Decidable Proposition Types *)
374 386
375 (** 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}% *) 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}% *)
376 388
389 (* begin hide *)
390 Definition baz := sumbool.
391 (* end hide *)
392
377 Print sumbool. 393 Print sumbool.
378 (** %\vspace{-.15in}% [[ 394 (** %\vspace{-.15in}% [[
379 Inductive sumbool (A : Prop) (B : Prop) : Set := 395 Inductive sumbool (A : Prop) (B : Prop) : Set :=
380 left : A -> {A} + {B} | right : B -> {A} + {B} 396 left : A -> {A} + {B} | right : B -> {A} + {B}
381 ]] 397 ]]
449 465
450 Definition eq_nat_dec' (n m : nat) : {n = m} + {n <> m}. 466 Definition eq_nat_dec' (n m : nat) : {n = m} + {n <> m}.
451 decide equality. 467 decide equality.
452 Defined. 468 Defined.
453 469
454 (** Curious readers can verify that the [decide equality] version extracts to the same OCaml code as our more manual version does. That OCaml code had one undesirable property, which is that it uses %\texttt{%#<tt>#Left#</tt>#%}% and %\texttt{%#<tt>#Right#</tt>#%}% constructors instead of the boolean values built into OCaml. We can fix this, by using Coq's facility for mapping Coq inductive types to OCaml variant types.%\index{Vernacular commands!Extract Inductive}% *) 470 (** Curious readers can verify that the [decide equality] version extracts to the same OCaml code as our more manual version does. That OCaml code had one undesirable property, which is that it uses <<Left>> and <<Right>> constructors instead of the boolean values built into OCaml. We can fix this, by using Coq's facility for mapping Coq inductive types to OCaml variant types.%\index{Vernacular commands!Extract Inductive}% *)
455 471
456 Extract Inductive sumbool => "bool" ["true" "false"]. 472 Extract Inductive sumbool => "bool" ["true" "false"].
457 Extraction eq_nat_dec'. 473 Extraction eq_nat_dec'.
458 474
459 (** %\begin{verbatim} 475 (** %\begin{verbatim}
482 | S n1 -> eq_nat_dec' n0 n1) 498 | S n1 -> eq_nat_dec' n0 n1)
483 </pre># *) 499 </pre># *)
484 500
485 (** %\smallskip% 501 (** %\smallskip%
486 502
487 We can build %``%#"#smart#"#%''% versions of the usual boolean operators and put them to good use in certified programming. For instance, here is a [sumbool] version of boolean %``%#"#or.#"#%''% *) 503 We can build "smart" versions of the usual boolean operators and put them to good use in certified programming. For instance, here is a [sumbool] version of boolean "or." *)
488 504
489 (* EX: Write a function that decides if an element belongs to a list. *) 505 (* EX: Write a function that decides if an element belongs to a list. *)
490 506
491 (* begin thide *) 507 (* begin thide *)
492 Notation "x || y" := (if x then Yes else Reduce y). 508 Notation "x || y" := (if x then Yes else Reduce y).
589 : {{m | 0 = S m}} 605 : {{m | 0 = S m}}
590 ]] 606 ]]
591 607
592 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]. *) 608 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]. *)
593 609
610 (* begin hide *)
611 Definition sumor' := sumor.
612 (* end hide *)
613
594 Print sumor. 614 Print sumor.
595 (** %\vspace{-.15in}% [[ 615 (** %\vspace{-.15in}% [[
596 Inductive sumor (A : Type) (B : Prop) : Type := 616 Inductive sumor (A : Type) (B : Prop) : Type :=
597 inleft : A -> A + {B} | inright : B -> A + {B} 617 inleft : A -> A + {B} | inright : B -> A + {B}
598 ]] 618 ]]
630 (** As with our other maximally expressive [pred] function, we arrive at quite simple output values, thanks to notations. *) 650 (** As with our other maximally expressive [pred] function, we arrive at quite simple output values, thanks to notations. *)
631 651
632 652
633 (** * Monadic Notations *) 653 (** * Monadic Notations *)
634 654
635 (** We can treat [maybe] like a monad%~\cite{Monads}\index{monad}\index{failure 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. *) 655 (** We can treat [maybe] like a monad%~\cite{Monads}\index{monad}\index{failure 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. *)
636 656
637 Notation "x <- e1 ; e2" := (match e1 with 657 Notation "x <- e1 ; e2" := (match e1 with
638 | Unknown => ?? 658 | Unknown => ??
639 | Found x _ => e2 659 | Found x _ => e2
640 end) 660 end)
653 m2 <- pred_strong7 n2; 673 m2 <- pred_strong7 n2;
654 [|(m1, m2)|]); tauto. 674 [|(m1, m2)|]); tauto.
655 Defined. 675 Defined.
656 (* end thide *) 676 (* end thide *)
657 677
658 (** We can build a [sumor] version of the %``%#"#bind#"#%''% notation and use it to write a similarly straightforward version of this function. %The operator rendered here as $\longleftarrow$ is noted in the source as a less-than character followed by two hyphens.% *) 678 (** We can build a [sumor] version of the "bind" notation and use it to write a similarly straightforward version of this function. %The operator rendered here as $\longleftarrow$ is noted in the source as a less-than character followed by two hyphens.% *)
659 679
660 Notation "x <-- e1 ; e2" := (match e1 with 680 Notation "x <-- e1 ; e2" := (match e1 with
661 | inright _ => !! 681 | inright _ => !!
662 | inleft (exist x _) => e2 682 | inleft (exist x _) => e2
663 end) 683 end)
714 (* begin thide *) 734 (* begin thide *)
715 Definition eq_type_dec : forall t1 t2 : type, {t1 = t2} + {t1 <> t2}. 735 Definition eq_type_dec : forall t1 t2 : type, {t1 = t2} + {t1 <> t2}.
716 decide equality. 736 decide equality.
717 Defined. 737 Defined.
718 738
719 (** Another notation complements the monadic notation for [maybe] that we defined earlier. Sometimes we want to include %``%#"#assertions#"#%''% in our procedures. That is, we want to run a decision procedure and fail if it fails; otherwise, we want to continue, with the proof that it produced made available to us. This infix notation captures that idea, for a procedure that returns an arbitrary two-constructor type. *) 739 (** Another notation complements the monadic notation for [maybe] that we defined earlier. Sometimes we want to include "assertions" in our procedures. That is, we want to run a decision procedure and fail if it fails; otherwise, we want to continue, with the proof that it produced made available to us. This infix notation captures that idea, for a procedure that returns an arbitrary two-constructor type. *)
720 740
721 Notation "e1 ;; e2" := (if e1 then e2 else ??) 741 Notation "e1 ;; e2" := (if e1 then e2 else ??)
722 (right associativity, at level 60). 742 (right associativity, at level 60).
723 743
724 (** With that notation defined, we can implement a [typeCheck] function, whose code is only more complex than what we would write in ML because it needs to include some extra type annotations. Every [[|e|]] expression adds a [hasType] proof obligation, and [crush] makes short work of them when we add [hasType]'s constructors as hints. *) 744 (** With that notation defined, we can implement a [typeCheck] function, whose code is only more complex than what we would write in ML because it needs to include some extra type annotations. Every [[|e|]] expression adds a [hasType] proof obligation, and [crush] makes short work of them when we add [hasType]'s constructors as hints. *)
843 | false -> Unknown))) 863 | false -> Unknown)))
844 </pre># *) 864 </pre># *)
845 865
846 (** %\smallskip% 866 (** %\smallskip%
847 867
848 We can adapt this implementation to use [sumor], so that we know our type-checker only fails on ill-typed inputs. First, we define an analogue to the %``%#"#assertion#"#%''% notation. *) 868 We can adapt this implementation to use [sumor], so that we know our type-checker only fails on ill-typed inputs. First, we define an analogue to the "assertion" notation. *)
849 869
850 (* begin thide *) 870 (* begin thide *)
851 Notation "e1 ;;; e2" := (if e1 then e2 else !!) 871 Notation "e1 ;;; e2" := (if e1 then e2 else !!)
852 (right associativity, at level 60). 872 (right associativity, at level 60).
853 873