Mercurial > cpdt > repo
comparison src/Subset.v @ 292:2c88fc1dbe33
A pass of double-quotes and LaTeX operator beautification
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 10 Nov 2010 16:31:04 -0500 |
parents | caa69851c78d |
children | 1b6c81e51799 |
comparison
equal
deleted
inserted
replaced
291:da9ccc6bf572 | 292:2c88fc1dbe33 |
---|---|
18 | 18 |
19 (** %\part{Programming with Dependent Types} | 19 (** %\part{Programming with Dependent Types} |
20 | 20 |
21 \chapter{Subset Types and Variations}% *) | 21 \chapter{Subset Types and Variations}% *) |
22 | 22 |
23 (** 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 %\textit{%#<i>#dependent types#</i>#%}% to integrate programming, specification, and proving into a single phase. *) | 23 (** 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 %\textit{%#<i>#dependent types#</i>#%}% to integrate programming, specification, and proving into a single phase. *) |
24 | 24 |
25 | 25 |
26 (** * Introducing Subset Types *) | 26 (** * Introducing Subset Types *) |
27 | 27 |
28 (** Let us consider several ways of implementing the natural number predecessor function. We start by displaying the definition from the standard library: *) | 28 (** Let us consider several ways of implementing the natural number predecessor function. We start by displaying the definition from the standard library: *) |
232 | O => fun _ => False_rec _ _ | 232 | O => fun _ => False_rec _ _ |
233 | S n' => fun _ => exist _ n' _ | 233 | S n' => fun _ => exist _ n' _ |
234 end). | 234 end). |
235 | 235 |
236 (* begin thide *) | 236 (* begin thide *) |
237 (** 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. We do most of the work with the [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: | 237 (** 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. We do most of the work with the [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: |
238 | 238 |
239 [[ | 239 [[ |
240 2 subgoals | 240 2 subgoals |
241 | 241 |
242 n : nat | 242 n : nat |
258 | S n' => fun _ => exist _ n' _ | 258 | S n' => fun _ => exist _ n' _ |
259 end); crush. | 259 end); crush. |
260 (* end thide *) | 260 (* end thide *) |
261 Defined. | 261 Defined. |
262 | 262 |
263 (** We end the "proof" with [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. Let us see what our proof script constructed. *) | 263 (** We end the %``%#"#proof#"#%''% with [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. Let us see what our proof script constructed. *) |
264 | 264 |
265 Print pred_strong4. | 265 Print pred_strong4. |
266 (** %\vspace{-.15in}% [[ | 266 (** %\vspace{-.15in}% [[ |
267 pred_strong4 = | 267 pred_strong4 = |
268 fun n : nat => | 268 fun n : nat => |
446 | S n1 -> eq_nat_dec' n0 n1) | 446 | S n1 -> eq_nat_dec' n0 n1) |
447 </pre># *) | 447 </pre># *) |
448 | 448 |
449 (** %\smallskip% | 449 (** %\smallskip% |
450 | 450 |
451 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." *) | 451 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.#"#%''% *) |
452 | 452 |
453 (* begin thide *) | 453 (* begin thide *) |
454 Notation "x || y" := (if x then Yes else Reduce y). | 454 Notation "x || y" := (if x then Yes else Reduce y). |
455 | 455 |
456 (** Let us use it for building a function that decides list membership. We need to assume the existence of an equality decision procedure for the type of list elements. *) | 456 (** Let us use it for building a function that decides list membership. We need to assume the existence of an equality decision procedure for the type of list elements. *) |
590 ]] *) | 590 ]] *) |
591 | 591 |
592 | 592 |
593 (** * Monadic Notations *) | 593 (** * Monadic Notations *) |
594 | 594 |
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. *) | 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. *) |
596 | 596 |
597 Notation "x <- e1 ; e2" := (match e1 with | 597 Notation "x <- e1 ; e2" := (match e1 with |
598 | Unknown => ?? | 598 | Unknown => ?? |
599 | Found x _ => e2 | 599 | Found x _ => e2 |
600 end) | 600 end) |
609 m1 <- pred_strong7 n1; | 609 m1 <- pred_strong7 n1; |
610 m2 <- pred_strong7 n2; | 610 m2 <- pred_strong7 n2; |
611 [[(m1, m2)]]); tauto. | 611 [[(m1, m2)]]); tauto. |
612 Defined. | 612 Defined. |
613 | 613 |
614 (** We can build a [sumor] version of the "bind" notation and use it to write a similarly straightforward version of this function. *) | 614 (** We can build a [sumor] version of the %``%#"#bind#"#%''% notation and use it to write a similarly straightforward version of this function. *) |
615 | 615 |
616 (** printing <-- $\longleftarrow$ *) | 616 (** printing <-- $\longleftarrow$ *) |
617 | 617 |
618 Notation "x <-- e1 ; e2" := (match e1 with | 618 Notation "x <-- e1 ; e2" := (match e1 with |
619 | inright _ => !! | 619 | inright _ => !! |
666 (* begin thide *) | 666 (* begin thide *) |
667 Definition eq_type_dec : forall t1 t2 : type, {t1 = t2} + {t1 <> t2}. | 667 Definition eq_type_dec : forall t1 t2 : type, {t1 = t2} + {t1 <> t2}. |
668 decide equality. | 668 decide equality. |
669 Defined. | 669 Defined. |
670 | 670 |
671 (** 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. *) | 671 (** 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. *) |
672 | 672 |
673 Notation "e1 ;; e2" := (if e1 then e2 else ??) | 673 Notation "e1 ;; e2" := (if e1 then e2 else ??) |
674 (right associativity, at level 60). | 674 (right associativity, at level 60). |
675 | 675 |
676 (** 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. *) | 676 (** 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. *) |
792 | false -> Unknown))) | 792 | false -> Unknown))) |
793 </pre># *) | 793 </pre># *) |
794 | 794 |
795 (** %\smallskip% | 795 (** %\smallskip% |
796 | 796 |
797 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. *) | 797 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. *) |
798 | 798 |
799 (* begin thide *) | 799 (* begin thide *) |
800 Notation "e1 ;;; e2" := (if e1 then e2 else !!) | 800 Notation "e1 ;;; e2" := (if e1 then e2 else !!) |
801 (right associativity, at level 60). | 801 (right associativity, at level 60). |
802 | 802 |
887 %\item%#<li># Define a function [bool_true_dec] that checks whether a boolean is true, with a maximally expressive dependent type. That is, the function should have type [forall b, {b = true} + {b = true -> False}]. #</li># | 887 %\item%#<li># Define a function [bool_true_dec] that checks whether a boolean is true, with a maximally expressive dependent type. That is, the function should have type [forall b, {b = true} + {b = true -> False}]. #</li># |
888 %\item%#<li># Define a function [decide] that determines whether a particular [prop] is true under a particular truth assignment. That is, the function should have type [forall (truth : var -> bool) (p : prop), {propDenote truth p} + {~ propDenote truth p}]. This function is probably easiest to write in the usual tactical style, instead of programming with [refine]. [bool_true_dec] may come in handy as a hint.#</li># | 888 %\item%#<li># Define a function [decide] that determines whether a particular [prop] is true under a particular truth assignment. That is, the function should have type [forall (truth : var -> bool) (p : prop), {propDenote truth p} + {~ propDenote truth p}]. This function is probably easiest to write in the usual tactical style, instead of programming with [refine]. [bool_true_dec] may come in handy as a hint.#</li># |
889 %\item%#<li># Define a function [negate] that returns a simplified version of the negation of a [prop]. That is, the function should have type [forall p : prop, {p' : prop | forall truth, propDenote truth p <-> ~ propDenote truth p'}]. To simplify a variable, just negate it. Simplify a negation by returning its argument. Simplify conjunctions and disjunctions using De Morgan's laws, negating the arguments recursively and switching the kind of connective. [decide] may be useful in some of the proof obligations, even if you do not use it in the computational part of [negate]'s definition. Lemmas like [decide] allow us to compensate for the lack of a general Law of the Excluded Middle in CIC.#</li># | 889 %\item%#<li># Define a function [negate] that returns a simplified version of the negation of a [prop]. That is, the function should have type [forall p : prop, {p' : prop | forall truth, propDenote truth p <-> ~ propDenote truth p'}]. To simplify a variable, just negate it. Simplify a negation by returning its argument. Simplify conjunctions and disjunctions using De Morgan's laws, negating the arguments recursively and switching the kind of connective. [decide] may be useful in some of the proof obligations, even if you do not use it in the computational part of [negate]'s definition. Lemmas like [decide] allow us to compensate for the lack of a general Law of the Excluded Middle in CIC.#</li># |
890 #</ol>#%\end{enumerate}% #</li># | 890 #</ol>#%\end{enumerate}% #</li># |
891 | 891 |
892 %\item%#<li># Implement the DPLL satisfiability decision procedure for boolean formulas in conjunctive normal form, with a dependent type that guarantees its correctness. An example of a reasonable type for this function would be [forall f : formula, {truth : tvals | formulaTrue truth f} + {forall truth, ~ formulaTrue truth f}]. Implement at least "the basic backtracking algorithm" as defined here: | 892 %\item%#<li># Implement the DPLL satisfiability decision procedure for boolean formulas in conjunctive normal form, with a dependent type that guarantees its correctness. An example of a reasonable type for this function would be [forall f : formula, {truth : tvals | formulaTrue truth f} + {forall truth, ~ formulaTrue truth f}]. Implement at least %``%#"#the basic backtracking algorithm#"#%''% as defined here: |
893 %\begin{center}\url{http://en.wikipedia.org/wiki/DPLL_algorithm}\end{center}% | 893 %\begin{center}\url{http://en.wikipedia.org/wiki/DPLL_algorithm}\end{center}% |
894 #<blockquote><a href="http://en.wikipedia.org/wiki/DPLL_algorithm">http://en.wikipedia.org/wiki/DPLL_algorithm</a></blockquote># | 894 #<blockquote><a href="http://en.wikipedia.org/wiki/DPLL_algorithm">http://en.wikipedia.org/wiki/DPLL_algorithm</a></blockquote># |
895 It might also be instructive to implement the unit propagation and pure literal elimination optimizations described there or some other optimizations that have been used in modern SAT solvers.#</li># | 895 It might also be instructive to implement the unit propagation and pure literal elimination optimizations described there or some other optimizations that have been used in modern SAT solvers.#</li># |
896 | 896 |
897 #</ol>#%\end{enumerate}% *) | 897 #</ol>#%\end{enumerate}% *) |