comparison src/MoreDep.v @ 283:756ce68e42fb

PC comments for MoreDep
author Adam Chlipala <adam@chlipala.net>
date Fri, 05 Nov 2010 11:36:36 -0400
parents d63cb5fbdce0
children 2c88fc1dbe33
comparison
equal deleted inserted replaced
282:caa69851c78d 283:756ce68e42fb
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:
70 70
71 (** Using [return] alone allowed us to express a dependency of the [match] result type on the %\textit{%#<i>#value#</i>#%}% of the discriminee. What [in] adds to our arsenal is a way of expressing a dependency on the %\textit{%#<i>#type#</i>#%}% of the discriminee. Specifically, the [n1] in the [in] clause above is a %\textit{%#<i>#binding occurrence#</i>#%}% whose scope is the [return] clause. 71 (** Using [return] alone allowed us to express a dependency of the [match] result type on the %\textit{%#<i>#value#</i>#%}% of the discriminee. What [in] adds to our arsenal is a way of expressing a dependency on the %\textit{%#<i>#type#</i>#%}% of the discriminee. Specifically, the [n1] in the [in] clause above is a %\textit{%#<i>#binding occurrence#</i>#%}% whose scope is the [return] clause.
72 72
73 We may use [in] clauses only to bind names for the arguments of an inductive type family. That is, each [in] clause must be an inductive type family name applied to a sequence of underscores and variable names of the proper length. The positions for %\textit{%#<i>#parameters#</i>#%}% to the type family must all be underscores. Parameters are those arguments declared with section variables or with entries to the left of the first colon in an inductive definition. They cannot vary depending on which constructor was used to build the discriminee, so Coq prohibits pointless matches on them. It is those arguments defined in the type to the right of the colon that we may name with [in] clauses. 73 We may use [in] clauses only to bind names for the arguments of an inductive type family. That is, each [in] clause must be an inductive type family name applied to a sequence of underscores and variable names of the proper length. The positions for %\textit{%#<i>#parameters#</i>#%}% to the type family must all be underscores. Parameters are those arguments declared with section variables or with entries to the left of the first colon in an inductive definition. They cannot vary depending on which constructor was used to build the discriminee, so Coq prohibits pointless matches on them. It is those arguments defined in the type to the right of the colon that we may name with [in] clauses.
74 74
75 Our [app] function could be typed in so-called %\textit{%#<i>#stratified#</i>#%}% type systems, which avoid true dependency. We could consider the length indices to lists to live in a separate, compile-time-only universe from the lists themselves. Our next example would be harder to implement in a stratified system. We write an injection function from regular lists to length-indexed lists. A stratified implementation would need to duplicate the definition of lists across compile-time and run-time versions, and the run-time versions would need to be indexed by the compile-time versions. *) 75 Our [app] function could be typed in so-called %\textit{%#<i>#stratified#</i>#%}% type systems, which avoid true dependency. That is, we could consider the length indices to lists to live in a separate, compile-time-only universe from the lists themselves. This stratification between a compile-time universe and a run-time universe, with no references to the latter in the former, gives rise to the terminology %``%#"#stratified.#"#%''% Our next example would be harder to implement in a stratified system. We write an injection function from regular lists to length-indexed lists. A stratified implementation would need to duplicate the definition of lists across compile-time and run-time versions, and the run-time versions would need to be indexed by the compile-time versions. *)
76 76
77 (* EX: Implement injection from normal lists *) 77 (* EX: Implement injection from normal lists *)
78 78
79 (* begin thide *) 79 (* begin thide *)
80 Fixpoint inject (ls : list A) : ilist (length ls) := 80 Fixpoint inject (ls : list A) : ilist (length ls) :=
96 Qed. 96 Qed.
97 (* end thide *) 97 (* end thide *)
98 98
99 (* EX: Implement statically-checked "car"/"hd" *) 99 (* EX: Implement statically-checked "car"/"hd" *)
100 100
101 (** Now let us attempt a function that is surprisingly tricky to write. In ML, the list head function raises an exception when passed an empty list. With length-indexed lists, we can rule out such invalid calls statically, and here is a first attempt at doing so. 101 (** Now let us attempt a function that is surprisingly tricky to write. In ML, the list head function raises an exception when passed an empty list. With length-indexed lists, we can rule out such invalid calls statically, and here is a first attempt at doing so. We write [???] as a placeholder for a term that we do not know how to write, not for any real Coq notation like those introduced in the previous chapter.
102 102
103 [[ 103 [[
104 Definition hd n (ls : ilist (S n)) : A := 104 Definition hd n (ls : ilist (S n)) : A :=
105 match ls with 105 match ls with
106 | Nil => ??? 106 | Nil => ???
141 Definition hd' n (ls : ilist n) := 141 Definition hd' n (ls : ilist n) :=
142 match ls in (ilist n) return (match n with O => unit | S _ => A end) with 142 match ls in (ilist n) return (match n with O => unit | S _ => A end) with
143 | Nil => tt 143 | Nil => tt
144 | Cons _ h _ => h 144 | Cons _ h _ => h
145 end. 145 end.
146
147 Check hd'.
148 (** %\vspace{-.15in}% [[
149 hd'
150 : forall n : nat, ilist n -> match n with
151 | 0 => unit
152 | S _ => A
153 end
154
155 ]] *)
146 156
147 Definition hd n (ls : ilist (S n)) : A := hd' ls. 157 Definition hd n (ls : ilist (S n)) : A := hd' ls.
148 (* end thide *) 158 (* end thide *)
149 159
150 (** We annotate our main [match] with a type that is itself a [match]. We write that the function [hd'] returns [unit] when the list is empty and returns the carried type [A] in all other cases. In the definition of [hd], we just call [hd']. Because the index of [ls] is known to be nonzero, the type checker reduces the [match] in the type of [hd'] to [A]. *) 160 (** We annotate our main [match] with a type that is itself a [match]. We write that the function [hd'] returns [unit] when the list is empty and returns the carried type [A] in all other cases. In the definition of [hd], we just call [hd']. Because the index of [ls] is known to be nonzero, the type checker reduces the [match] in the type of [hd'] to [A]. *)
402 | BlackNode _ _ _ t1 _ t2 => S (f (depth t1) (depth t2)) 412 | BlackNode _ _ _ t1 _ t2 => S (f (depth t1) (depth t2))
403 end. 413 end.
404 End depth. 414 End depth.
405 415
406 (** Our proof of balanced-ness decomposes naturally into a lower bound and an upper bound. We prove the lower bound first. Unsurprisingly, a tree's black depth provides such a bound on the minimum path length. We use the richly-typed procedure [min_dec] to do case analysis on whether [min X Y] equals [X] or [Y]. *) 416 (** Our proof of balanced-ness decomposes naturally into a lower bound and an upper bound. We prove the lower bound first. Unsurprisingly, a tree's black depth provides such a bound on the minimum path length. We use the richly-typed procedure [min_dec] to do case analysis on whether [min X Y] equals [X] or [Y]. *)
417
418 Check min_dec.
419 (** %\vspace{-.15in}% [[
420 min_dec
421 : forall n m : nat, {min n m = n} + {min n m = m}
422
423 ]] *)
407 424
408 Theorem depth_min : forall c n (t : rbtree c n), depth min t >= n. 425 Theorem depth_min : forall c n (t : rbtree c n), depth min t >= n.
409 induction t; crush; 426 induction t; crush;
410 match goal with 427 match goal with
411 | [ |- context[min ?X ?Y] ] => destruct (min_dec X Y) 428 | [ |- context[min ?X ?Y] ] => destruct (min_dec X Y)
728 present_insert. 745 present_insert.
729 Qed. 746 Qed.
730 End present. 747 End present.
731 End insert. 748 End insert.
732 749
750 (** We can generate executable OCaml code with the command [Recursive Extraction insert], which also automatically outputs the OCaml versions of all of [insert]'s dependencies. In our previous extractions, we wound up with clean OCaml code. Here, we find uses of %\texttt{%#<tt>#Obj.magic#</tt>#%}%, OCaml's unsafe cast operator for tweaking the apparent type of an expression in an arbitrary way. Casts appear for this example because the return type of [insert] depends on the %\textit{%#<i>#value#</i>#%}% of the function's argument, a pattern which OCaml cannot handle. Since Coq's type system is much more expressive than OCaml's, such casts are unavoidable in general. Since the OCaml type-checker is no longer checking full safety of programs, we must rely on Coq's extractor to use casts only in provably safe ways. *)
751
733 752
734 (** * A Certified Regular Expression Matcher *) 753 (** * A Certified Regular Expression Matcher *)
735 754
736 (** Another interesting example is regular expressions with dependent types that express which predicates over strings particular regexps implement. We can then assign a dependent type to a regular expression matching function, guaranteeing that it always decides the string property that we expect it to decide. 755 (** Another interesting example is regular expressions with dependent types that express which predicates over strings particular regexps implement. We can then assign a dependent type to a regular expression matching function, guaranteeing that it always decides the string property that we expect it to decide.
737 756
738 Before defining the syntax of expressions, it is helpful to define an inductive type capturing the meaning of the Kleene star. We use Coq's string support, which comes through a combination of the [Strings] library and some parsing notations built into Coq. Operators like [++] and functions like [length] that we know from lists are defined again for strings. Notation scopes help us control which versions we want to use in particular contexts. *) 757 Before defining the syntax of expressions, it is helpful to define an inductive type capturing the meaning of the Kleene star. That is, a string [s] matches regular expression [star e] if and only if [s] can be decomposed into a sequence of substrings that all match [e]. We use Coq's string support, which comes through a combination of the [Strings] library and some parsing notations built into Coq. Operators like [++] and functions like [length] that we know from lists are defined again for strings. Notation scopes help us control which versions we want to use in particular contexts. *)
739 758
740 Require Import Ascii String. 759 Require Import Ascii String.
741 Open Scope string_scope. 760 Open Scope string_scope.
742 761
743 Section star. 762 Section star.
749 P s1 768 P s1
750 -> star s2 769 -> star s2
751 -> star (s1 ++ s2). 770 -> star (s1 ++ s2).
752 End star. 771 End star.
753 772
754 (** Now we can make our first attempt at defining a [regexp] type that is indexed by predicates on strings. Here is a reasonable-looking definition that is restricted to constant characters and concatenation. 773 (** Now we can make our first attempt at defining a [regexp] type that is indexed by predicates on strings. Here is a reasonable-looking definition that is restricted to constant characters and concatenation. We use the constructor [String], which is the analogue of list cons for the type [string], where [""] is like list nil.
755 774
756 [[ 775 [[
757 Inductive regexp : (string -> Prop) -> Set := 776 Inductive regexp : (string -> Prop) -> Set :=
758 | Char : forall ch : ascii, 777 | Char : forall ch : ascii,
759 regexp (fun s => s = String ch "") 778 regexp (fun s => s = String ch "")
1173 match goal with 1192 match goal with
1174 | [ H : _ |- _ ] => generalize (H _ _ (refl_equal _)) 1193 | [ H : _ |- _ ] => generalize (H _ _ (refl_equal _))
1175 end; tauto. 1194 end; tauto.
1176 Defined. 1195 Defined.
1177 1196
1197 (** It is interesting to pause briefly to consider alternate implementations of [matches]. Dependent types give us much latitude in how specific correctness properties may be encoded with types. For instance, we could have made [regexp] a non-indexed inductive type, along the lines of what is possible in traditional ML and Haskell. We could then have implemented a recursive function to map [regexp]s to their intended meanings, much as we have done with types and programs in other examples. That style is compatible with the [refine]-based approach that we have used here, and it might be an interesting exercise to redo the code from this subsection in that alternate style or some further encoding of the reader's choice. The main advantage of indexed inductive types is that they generally lead to the smallest amount of code. *)
1198
1178 (* begin hide *) 1199 (* begin hide *)
1179 Example hi := Concat (Char "h"%char) (Char "i"%char). 1200 Example hi := Concat (Char "h"%char) (Char "i"%char).
1180 Eval simpl in matches hi "hi". 1201 Eval simpl in matches hi "hi".
1181 Eval simpl in matches hi "bye". 1202 Eval simpl in matches hi "bye".
1182 1203
1183 Example a_b := Or (Char "a"%char) (Char "b"%char). 1204 Example a_b := Or (Char "a"%char) (Char "b"%char).
1184 Eval simpl in matches a_b "". 1205 Eval simpl in matches a_b "".
1185 Eval simpl in matches a_b "a". 1206 Eval simpl in matches a_b "a".
1186 Eval simpl in matches a_b "aa". 1207 Eval simpl in matches a_b "aa".
1187 Eval simpl in matches a_b "b". 1208 Eval simpl in matches a_b "b".
1209 (* end hide *)
1210
1211 (** Many regular expression matching problems are easy to test. The reader may run each of the following queries to verify that it gives the correct answer. *)
1188 1212
1189 Example a_star := Star (Char "a"%char). 1213 Example a_star := Star (Char "a"%char).
1190 Eval simpl in matches a_star "". 1214 Eval simpl in matches a_star "".
1191 Eval simpl in matches a_star "a". 1215 Eval simpl in matches a_star "a".
1192 Eval simpl in matches a_star "b". 1216 Eval simpl in matches a_star "b".
1193 Eval simpl in matches a_star "aa". 1217 Eval simpl in matches a_star "aa".
1194 (* end hide *) 1218
1219 (** Evaluation inside Coq does not scale very well, so it is easy to build other tests that run for hours or more. Such cases are better suited to execution with the extracted OCaml code. *)
1195 1220
1196 1221
1197 (** * Exercises *) 1222 (** * Exercises *)
1198 1223
1199 (** %\begin{enumerate}%#<ol># 1224 (** %\begin{enumerate}%#<ol>#