Mercurial > cpdt > repo
comparison src/MoreDep.v @ 380:31fa03bc0f18
Get it to build with Coq 8.4
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Thu, 29 Mar 2012 18:10:52 -0400 |
parents | d1276004eec9 |
children | b911d0df5eee |
comparison
equal
deleted
inserted
replaced
379:e23d41ae63be | 380:31fa03bc0f18 |
---|---|
556 A quick word of encouragement: After writing this code, even I do not understand the precise details of how balancing works! I consulted Chris Okasaki's paper %``%#"#Red-Black Trees in a Functional Setting#"#%''~\cite{Okasaki}% and transcribed the code to use dependent types. Luckily, the details are not so important here; types alone will tell us that insertion preserves balanced-ness, and we will prove that insertion produces trees containing the right keys.*) | 556 A quick word of encouragement: After writing this code, even I do not understand the precise details of how balancing works! I consulted Chris Okasaki's paper %``%#"#Red-Black Trees in a Functional Setting#"#%''~\cite{Okasaki}% and transcribed the code to use dependent types. Luckily, the details are not so important here; types alone will tell us that insertion preserves balanced-ness, and we will prove that insertion produces trees containing the right keys.*) |
557 | 557 |
558 Definition balance1 n (a : rtree n) (data : nat) c2 := | 558 Definition balance1 n (a : rtree n) (data : nat) c2 := |
559 match a in rtree n return rbtree c2 n | 559 match a in rtree n return rbtree c2 n |
560 -> { c : color & rbtree c (S n) } with | 560 -> { c : color & rbtree c (S n) } with |
561 | RedNode' _ _ _ t1 y t2 => | 561 | RedNode' _ c0 _ t1 y t2 => |
562 match t1 in rbtree c n return rbtree _ n -> rbtree c2 n | 562 match t1 in rbtree c n return rbtree c0 n -> rbtree c2 n |
563 -> { c : color & rbtree c (S n) } with | 563 -> { c : color & rbtree c (S n) } with |
564 | RedNode _ a x b => fun c d => | 564 | RedNode _ a x b => fun c d => |
565 {<RedNode (BlackNode a x b) y (BlackNode c data d)>} | 565 {<RedNode (BlackNode a x b) y (BlackNode c data d)>} |
566 | t1' => fun t2 => | 566 | t1' => fun t2 => |
567 match t2 in rbtree c n return rbtree _ n -> rbtree c2 n | 567 match t2 in rbtree c n return rbtree Black n -> rbtree c2 n |
568 -> { c : color & rbtree c (S n) } with | 568 -> { c : color & rbtree c (S n) } with |
569 | RedNode _ b x c => fun a d => | 569 | RedNode _ b x c => fun a d => |
570 {<RedNode (BlackNode a y b) x (BlackNode c data d)>} | 570 {<RedNode (BlackNode a y b) x (BlackNode c data d)>} |
571 | b => fun a t => {<BlackNode (RedNode a y b) data t>} | 571 | b => fun a t => {<BlackNode (RedNode a y b) data t>} |
572 end t1' | 572 end t1' |
579 | 579 |
580 Here is the symmetric function [balance2], for cases where the possibly invalid tree appears on the right rather than on the left. *) | 580 Here is the symmetric function [balance2], for cases where the possibly invalid tree appears on the right rather than on the left. *) |
581 | 581 |
582 Definition balance2 n (a : rtree n) (data : nat) c2 := | 582 Definition balance2 n (a : rtree n) (data : nat) c2 := |
583 match a in rtree n return rbtree c2 n -> { c : color & rbtree c (S n) } with | 583 match a in rtree n return rbtree c2 n -> { c : color & rbtree c (S n) } with |
584 | RedNode' _ _ _ t1 z t2 => | 584 | RedNode' _ c0 _ t1 z t2 => |
585 match t1 in rbtree c n return rbtree _ n -> rbtree c2 n | 585 match t1 in rbtree c n return rbtree c0 n -> rbtree c2 n |
586 -> { c : color & rbtree c (S n) } with | 586 -> { c : color & rbtree c (S n) } with |
587 | RedNode _ b y c => fun d a => | 587 | RedNode _ b y c => fun d a => |
588 {<RedNode (BlackNode a data b) y (BlackNode c z d)>} | 588 {<RedNode (BlackNode a data b) y (BlackNode c z d)>} |
589 | t1' => fun t2 => | 589 | t1' => fun t2 => |
590 match t2 in rbtree c n return rbtree _ n -> rbtree c2 n | 590 match t2 in rbtree c n return rbtree Black n -> rbtree c2 n |
591 -> { c : color & rbtree c (S n) } with | 591 -> { c : color & rbtree c (S n) } with |
592 | RedNode _ c z' d => fun b a => | 592 | RedNode _ c z' d => fun b a => |
593 {<RedNode (BlackNode a data b) z (BlackNode c z' d)>} | 593 {<RedNode (BlackNode a data b) z (BlackNode c z' d)>} |
594 | b => fun a t => {<BlackNode t data (RedNode a z b)>} | 594 | b => fun a t => {<BlackNode t data (RedNode a z b)>} |
595 end t1' | 595 end t1' |
1130 refine (fix F (l : nat) : {exists l', S l' <= l | 1130 refine (fix F (l : nat) : {exists l', S l' <= l |
1131 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} | 1131 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} |
1132 + {forall l', S l' <= l | 1132 + {forall l', S l' <= l |
1133 -> ~ P (substring n (S l') s) | 1133 -> ~ P (substring n (S l') s) |
1134 \/ ~ P' (substring (n + S l') (length s - (n + S l')) s)} := | 1134 \/ ~ P' (substring (n + S l') (length s - (n + S l')) s)} := |
1135 match l with | 1135 match l return {exists l', S l' <= l |
1136 /\ P (substring n (S l') s) /\ P' (substring (n + S l') (length s - (n + S l')) s)} | |
1137 + {forall l', S l' <= l | |
1138 -> ~ P (substring n (S l') s) | |
1139 \/ ~ P' (substring (n + S l') (length s - (n + S l')) s)} with | |
1136 | O => _ | 1140 | O => _ |
1137 | S l' => | 1141 | S l' => |
1138 (P_dec (substring n (S l') s) && P'_dec (n' := n + S l') _) | 1142 (P_dec (substring n (S l') s) && P'_dec (n' := n + S l') _) |
1139 || F l' | 1143 || F l' |
1140 end); clear F; crush; eauto 7; | 1144 end); clear F; crush; eauto 7; |
1184 | [ H1 : _ < _ - _, H2 : forall l' : nat, _ <= _ - _ -> _ |- _ ] => | 1188 | [ H1 : _ < _ - _, H2 : forall l' : nat, _ <= _ - _ -> _ |- _ ] => |
1185 generalize (H2 _ (lt_le_S _ _ H1)); tauto | 1189 generalize (H2 _ (lt_le_S _ _ H1)); tauto |
1186 end. | 1190 end. |
1187 Defined. | 1191 Defined. |
1188 | 1192 |
1189 (** Finally, we have [dec_star]. It has a straightforward implementation. We introduce a spurious match on [s] so that [simpl] will know to reduce calls to [dec_star]. The heuristic that [simpl] uses is only to unfold identifier definitions when doing so would simplify some [match] expression. *) | 1193 (** Finally, we have [dec_star], defined by straightforward reduction from [dec_star']. *) |
1190 | 1194 |
1191 Definition dec_star : {star P s} + {~ star P s}. | 1195 Definition dec_star : {star P s} + {~ star P s}. |
1192 refine (match s return _ with | 1196 refine (Reduce (dec_star' (n := length s) 0 _)); crush. |
1193 | "" => Reduce (dec_star' (n := length s) 0 _) | |
1194 | _ => Reduce (dec_star' (n := length s) 0 _) | |
1195 end); crush. | |
1196 Defined. | 1197 Defined. |
1197 End dec_star. | 1198 End dec_star. |
1198 | 1199 |
1199 (* begin hide *) | 1200 (* begin hide *) |
1200 Lemma app_cong : forall x1 y1 x2 y2, | 1201 Lemma app_cong : forall x1 y1 x2 y2, |
1224 | 1225 |
1225 (** 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. *) | 1226 (** 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. *) |
1226 | 1227 |
1227 (* begin hide *) | 1228 (* begin hide *) |
1228 Example hi := Concat (Char "h"%char) (Char "i"%char). | 1229 Example hi := Concat (Char "h"%char) (Char "i"%char). |
1229 Eval simpl in matches hi "hi". | 1230 Eval hnf in matches hi "hi". |
1230 Eval simpl in matches hi "bye". | 1231 Eval hnf in matches hi "bye". |
1231 | 1232 |
1232 Example a_b := Or (Char "a"%char) (Char "b"%char). | 1233 Example a_b := Or (Char "a"%char) (Char "b"%char). |
1233 Eval simpl in matches a_b "". | 1234 Eval hnf in matches a_b "". |
1234 Eval simpl in matches a_b "a". | 1235 Eval hnf in matches a_b "a". |
1235 Eval simpl in matches a_b "aa". | 1236 Eval hnf in matches a_b "aa". |
1236 Eval simpl in matches a_b "b". | 1237 Eval hnf in matches a_b "b". |
1237 (* end hide *) | 1238 (* end hide *) |
1238 | 1239 |
1239 (** 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. *) | 1240 (** 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. We use evaluation strategy %\index{tactics!hnf}%[hnf] to reduce each term to %\index{head-normal form}\emph{%#<i>#head-normal form#</i>#%}%, where the datatype constructor used to build its value is known. *) |
1240 | 1241 |
1241 Example a_star := Star (Char "a"%char). | 1242 Example a_star := Star (Char "a"%char). |
1242 Eval simpl in matches a_star "". | 1243 Eval hnf in matches a_star "". |
1243 Eval simpl in matches a_star "a". | 1244 Eval hnf in matches a_star "a". |
1244 Eval simpl in matches a_star "b". | 1245 Eval hnf in matches a_star "b". |
1245 Eval simpl in matches a_star "aa". | 1246 Eval hnf in matches a_star "aa". |
1246 | 1247 |
1247 (** 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. *) | 1248 (** 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. *) |