comparison src/Subset.v @ 398:05efde66559d

Get it working in Coq 8.4beta1; use nice coqdoc notation for italics
author Adam Chlipala <adam@chlipala.net>
date Wed, 06 Jun 2012 11:25:13 -0400
parents 4b1242b277b2
children 1edeec5d5d0c
comparison
equal deleted inserted replaced
397:d62ed7381a0b 398:05efde66559d
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 %\index{dependent types}\textit{%#<i>#dependent types#</i>#%}% 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. *) 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 %\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. *)
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: *)
67 match n with 67 match n with
68 | O => fun pf : 0 > 0 => match zgtz pf with end 68 | O => fun pf : 0 > 0 => match zgtz pf with end
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 _proof_ 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 _dependent_ type, because its type depends on the _value_ of the argument [n].
73 73
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. *) 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 _implicit_, since it can be deduced from the type of the second argument, so we need not write [n] in function calls. *)
75 75
76 Theorem two_gt0 : 2 > 0. 76 Theorem two_gt0 : 2 > 0.
77 crush. 77 crush.
78 Qed. 78 Qed.
79 79
102 "0 > 0" 102 "0 > 0"
103 >> 103 >>
104 104
105 The term [zgtz pf] fails to type-check. Somehow the type checker has failed to take into account information that follows from which [match] branch that term appears in. The problem is that, by default, [match] does not let us use such implied information. To get refined typing, we must always rely on [match] annotations, either written explicitly or inferred. 105 The term [zgtz pf] fails to type-check. Somehow the type checker has failed to take into account information that follows from which [match] branch that term appears in. The problem is that, by default, [match] does not let us use such implied information. To get refined typing, we must always rely on [match] annotations, either written explicitly or inferred.
106 106
107 In this case, we must use a [return] annotation to declare the relationship between the %\textit{%#<i>#value#</i>#%}% of the [match] discriminee and the %\textit{%#<i>#type#</i>#%}% of the result. There is no annotation that lets us declare a relationship between the discriminee and the type of a variable that is already in scope; hence, we delay the binding of [pf], so that we can use the [return] annotation to express the needed relationship. 107 In this case, we must use a [return] annotation to declare the relationship between the _value_ of the [match] discriminee and the _type_ of the result. There is no annotation that lets us declare a relationship between the discriminee and the type of a variable that is already in scope; hence, we delay the binding of [pf], so that we can use the [return] annotation to express the needed relationship.
108 108
109 We are lucky that Coq's heuristics infer the [return] clause (specifically, [return n > 0 -> nat]) for us in this case. *) 109 We are lucky that Coq's heuristics infer the [return] clause (specifically, [return n > 0 -> nat]) for us in this case. *)
110 110
111 Definition pred_strong1' (n : nat) : n > 0 -> nat := 111 Definition pred_strong1' (n : nat) : n > 0 -> nat :=
112 match n return n > 0 -> nat with 112 match n return n > 0 -> nat with
113 | O => fun pf : 0 > 0 => match zgtz pf with end 113 | O => fun pf : 0 > 0 => match zgtz pf with end
114 | S n' => fun _ => n' 114 | S n' => fun _ => n'
115 end. 115 end.
116 116
117 (** By making explicit the functional relationship between value [n] and the result type of the [match], we guide Coq toward proper type checking. The clause for this example follows by simple copying of the original annotation on the definition. In general, however, the [match] annotation inference problem is undecidable. The known undecidable problem of %\index{higher-order unification}\textit{%#<i>#higher-order unification#</i>#%}~\cite{HOU}% reduces to the [match] type inference problem. Over time, Coq is enhanced with more and more heuristics to get around this problem, but there must always exist [match]es whose types Coq cannot infer without annotations. 117 (** By making explicit the functional relationship between value [n] and the result type of the [match], we guide Coq toward proper type checking. The clause for this example follows by simple copying of the original annotation on the definition. In general, however, the [match] annotation inference problem is undecidable. The known undecidable problem of %\index{higher-order unification}%_higher-order unification_ %\cite{HOU}% reduces to the [match] type inference problem. Over time, Coq is enhanced with more and more heuristics to get around this problem, but there must always exist [match]es whose types Coq cannot infer without annotations.
118 118
119 Let us now take a look at the OCaml code Coq generates for [pred_strong1]. *) 119 Let us now take a look at the OCaml code Coq generates for [pred_strong1]. *)
120 120
121 Extraction pred_strong1. 121 Extraction pred_strong1.
122 122
136 | S n' -> n' 136 | S n' -> n'
137 </pre># *) 137 </pre># *)
138 138
139 (** 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. 139 (** 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.
140 140
141 We can reimplement our dependently typed [pred] based on %\index{subset types}\textit{%#<i>#subset types#</i>#%}%, defined in the standard library with the type family %\index{Gallina terms!sig}%[sig]. *) 141 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]. *)
142 142
143 Print sig. 143 Print sig.
144 (** %\vspace{-.15in}% [[ 144 (** %\vspace{-.15in}% [[
145 Inductive sig (A : Type) (P : A -> Prop) : Type := 145 Inductive sig (A : Type) (P : A -> Prop) : Type :=
146 exist : forall x : A, P x -> sig P 146 exist : forall x : A, P x -> sig P
266 | S n' => fun _ => exist _ n' _ 266 | S n' => fun _ => exist _ n' _
267 end); crush. 267 end); crush.
268 (* end thide *) 268 (* end thide *)
269 Defined. 269 Defined.
270 270
271 (** 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}\emph{%#<i>#transparent#</i>#%}%, allowing it to be unfolded; while [Qed] marks an identifier as %\index{opaque}\emph{%#<i>#opaque#</i>#%}%, preventing unfolding.) Let us see what our proof script constructed. *) 271 (** 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. *)
272 272
273 Print pred_strong4. 273 Print pred_strong4.
274 (** %\vspace{-.15in}% [[ 274 (** %\vspace{-.15in}% [[
275 pred_strong4 = 275 pred_strong4 =
276 fun n : nat => 276 fun n : nat =>
634 | Unknown => ?? 634 | Unknown => ??
635 | Found x _ => e2 635 | Found x _ => e2
636 end) 636 end)
637 (right associativity, at level 60). 637 (right associativity, at level 60).
638 638
639 (** The meaning of [x <- e1; e2] is: First run [e1]. If it fails to find an answer, then announce failure for our derived computation, too. If [e1] %\textit{%#<i>#does#</i>#%}% find an answer, pass that answer on to [e2] to find the final result. The variable [x] can be considered bound in [e2]. 639 (** The meaning of [x <- e1; e2] is: First run [e1]. If it fails to find an answer, then announce failure for our derived computation, too. If [e1] _does_ find an answer, pass that answer on to [e2] to find the final result. The variable [x] can be considered bound in [e2].
640 640
641 This notation is very helpful for composing richly typed procedures. For instance, here is a very simple implementation of a function to take the predecessors of two naturals at once. *) 641 This notation is very helpful for composing richly typed procedures. For instance, here is a very simple implementation of a function to take the predecessors of two naturals at once. *)
642 642
643 (* EX: Write a function that tries to compute predecessors of two [nat]s at once. *) 643 (* EX: Write a function that tries to compute predecessors of two [nat]s at once. *)
644 644