comparison src/MoreDep.v @ 475:1fd4109f7b31

Batch of changes based on proofreader feedback
author Adam Chlipala <adam@chlipala.net>
date Mon, 22 Oct 2012 14:23:52 -0400
parents 4320c1a967c2
children 417450ccceda
comparison
equal deleted inserted replaced
474:d9e1fb184672 475:1fd4109f7b31
104 104
105 << 105 <<
106 Error: Non exhaustive pattern-matching: no clause found for pattern Nil 106 Error: Non exhaustive pattern-matching: no clause found for pattern Nil
107 >> 107 >>
108 108
109 Unlike in ML, we cannot use inexhaustive pattern matching, because there is no conception of a <<Match>> exception to be thrown. In fact, recent versions of Coq _do_ allow this, by implicit translation to a [match] that considers all constructors. It is educational to discover that encoding ourselves directly. We might try using an [in] clause somehow. 109 Unlike in ML, we cannot use inexhaustive pattern matching, because there is no conception of a <<Match>> exception to be thrown. In fact, recent versions of Coq _do_ allow this, by implicit translation to a [match] that considers all constructors. It is educational to discover such an encoding for ourselves. We might try using an [in] clause somehow.
110 110
111 [[ 111 [[
112 Definition hd n (ls : ilist (S n)) : A := 112 Definition hd n (ls : ilist (S n)) : A :=
113 match ls in (ilist (S n)) with 113 match ls in (ilist (S n)) with
114 | Cons _ h _ => h 114 | Cons _ h _ => h
376 User error: e1 is used in hypothesis e 376 User error: e1 is used in hypothesis e
377 >> 377 >>
378 378
379 Coq gives us another cryptic error message. Like so many others, this one basically means that Coq is not able to build some proof about dependent types. It is hard to generate helpful and specific error messages for problems like this, since that would require some kind of understanding of the dependency structure of a piece of code. We will encounter many examples of case-specific tricks for recovering from errors like this one. 379 Coq gives us another cryptic error message. Like so many others, this one basically means that Coq is not able to build some proof about dependent types. It is hard to generate helpful and specific error messages for problems like this, since that would require some kind of understanding of the dependency structure of a piece of code. We will encounter many examples of case-specific tricks for recovering from errors like this one.
380 380
381 For our current proof, we can use a tactic [dep_destruct]%\index{tactics!dep\_destruct}% defined in the book [CpdtTactics] module. General elimination/inversion of dependently typed hypotheses is undecidable, since it must be implemented with [match] expressions that have the restriction on [in] clauses that we have already discussed. The tactic [dep_destruct] makes a best effort to handle some common cases, relying upon the more primitive %\index{tactics!dependent destruction}%[dependent destruction] tactic that comes with Coq. In a future chapter, we will learn about the explicit manipulation of equality proofs that is behind [dep_destruct]'s implementation in Ltac, but for now, we treat it as a useful black box. (In Chapter 12, we will also see how [dependent destruction] forces us to make a larger philosophical commitment about our logic than we might like, and we will see some workarounds.) *) 381 For our current proof, we can use a tactic [dep_destruct]%\index{tactics!dep\_destruct}% defined in the book's [CpdtTactics] module. General elimination/inversion of dependently typed hypotheses is undecidable, since it must be implemented with [match] expressions that have the restriction on [in] clauses that we have already discussed. The tactic [dep_destruct] makes a best effort to handle some common cases, relying upon the more primitive %\index{tactics!dependent destruction}%[dependent destruction] tactic that comes with Coq. In a future chapter, we will learn about the explicit manipulation of equality proofs that is behind [dep_destruct]'s implementation in Ltac, but for now, we treat it as a useful black box. (In Chapter 12, we will also see how [dependent destruction] forces us to make a larger philosophical commitment about our logic than we might like, and we will see some workarounds.) *)
382 382
383 dep_destruct (cfold e1). 383 dep_destruct (cfold e1).
384 384
385 (** This successfully breaks the subgoal into 5 new subgoals, one for each constructor of [exp] that could produce an [exp Nat]. Note that [dep_destruct] is successful in ruling out the other cases automatically, in effect automating some of the work that we have done manually in implementing functions like [hd] and [pairOut]. 385 (** This successfully breaks the subgoal into 5 new subgoals, one for each constructor of [exp] that could produce an [exp Nat]. Note that [dep_destruct] is successful in ruling out the other cases automatically, in effect automating some of the work that we have done manually in implementing functions like [hd] and [pairOut].
386 386
403 (** With this example, we get a first taste of how to build automated proofs that adapt automatically to changes in function definitions. *) 403 (** With this example, we get a first taste of how to build automated proofs that adapt automatically to changes in function definitions. *)
404 404
405 405
406 (** * Dependently Typed Red-Black Trees *) 406 (** * Dependently Typed Red-Black Trees *)
407 407
408 (** Red-black trees are a favorite purely functional data structure with an interesting invariant. We can use dependent types to enforce that operations on red-black trees preserve the invariant. For simplicity, we specialize our red-black trees to represent sets of [nat]s. *) 408 (** Red-black trees are a favorite purely functional data structure with an interesting invariant. We can use dependent types to guarantee that operations on red-black trees preserve the invariant. For simplicity, we specialize our red-black trees to represent sets of [nat]s. *)
409 409
410 Inductive color : Set := Red | Black. 410 Inductive color : Set := Red | Black.
411 411
412 Inductive rbtree : color -> nat -> Set := 412 Inductive rbtree : color -> nat -> Set :=
413 | Leaf : rbtree Black 0 413 | Leaf : rbtree Black 0
1101 1101
1102 Variable P' : string -> Prop. 1102 Variable P' : string -> Prop.
1103 Variable P'_dec : forall n' : nat, n' > n 1103 Variable P'_dec : forall n' : nat, n' > n
1104 -> {P' (substring n' (length s - n') s)} 1104 -> {P' (substring n' (length s - n') s)}
1105 + {~ P' (substring n' (length s - n') s)}. 1105 + {~ P' (substring n' (length s - n') s)}.
1106
1106 (** When we use [dec_star''], we will instantiate [P'_dec] with a function for continuing the search for more instances of [P] in [s]. *) 1107 (** When we use [dec_star''], we will instantiate [P'_dec] with a function for continuing the search for more instances of [P] in [s]. *)
1107 1108
1108 (** Now we come to [dec_star''] itself. It takes as an input a natural [l] that records how much of the string has been searched so far, as we did for [split']. The return type expresses that [dec_star''] is looking for an index into [s] that splits [s] into a nonempty prefix and a suffix, such that the prefix satisfies [P] and the suffix satisfies [P']. *) 1109 (** Now we come to [dec_star''] itself. It takes as an input a natural [l] that records how much of the string has been searched so far, as we did for [split']. The return type expresses that [dec_star''] is looking for an index into [s] that splits [s] into a nonempty prefix and a suffix, such that the prefix satisfies [P] and the suffix satisfies [P']. *)
1109 1110
1110 Definition dec_star'' : forall l : nat, 1111 Definition dec_star'' : forall l : nat,