comparison src/DataStruct.v @ 205:f05514cc6c0d

'make doc' works with 8.2
author Adam Chlipala <adamc@hcoop.net>
date Fri, 06 Nov 2009 12:15:05 -0500
parents cbf2f74a5130
children f8bcd33bdd91
comparison
equal deleted inserted replaced
204:cbf2f74a5130 205:f05514cc6c0d
53 match idx with 53 match idx with
54 | First _ => x 54 | First _ => x
55 | Next _ idx' => get ls' idx' 55 | Next _ idx' => get ls' idx'
56 end 56 end
57 end. 57 end.
58
59 ]]
58 60
59 We apply the usual wisdom of delaying arguments in [Fixpoint]s so that they may be included in [return] clauses. This still leaves us with a quandary in each of the [match] cases. First, we need to figure out how to take advantage of the contradiction in the [Nil] case. Every [index] has a type of the form [S n], which cannot unify with the [O] value that we learn for [n] in the [Nil] case. The solution we adopt is another case of [match]-within-[return]. 61 We apply the usual wisdom of delaying arguments in [Fixpoint]s so that they may be included in [return] clauses. This still leaves us with a quandary in each of the [match] cases. First, we need to figure out how to take advantage of the contradiction in the [Nil] case. Every [index] has a type of the form [S n], which cannot unify with the [O] value that we learn for [n] in the [Nil] case. The solution we adopt is another case of [match]-within-[return].
60 62
61 [[ 63 [[
62 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A := 64 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A :=
74 | First _ => x 76 | First _ => x
75 | Next _ idx' => get ls' idx' 77 | Next _ idx' => get ls' idx'
76 end 78 end
77 end. 79 end.
78 80
81 ]]
82
79 Now the first [match] case type-checks, and we see that the problem with the [Cons] case is that the pattern-bound variable [idx'] does not have an apparent type compatible with [ls']. We need to use [match] annotations to make the relationship explicit. Unfortunately, the usual trick of postponing argument binding will not help us here. We need to match on both [ls] and [idx]; one or the other must be matched first. To get around this, we apply a trick that we will call "the convoy pattern," introducing a new function and applying it immediately, to satisfy the type checker. 83 Now the first [match] case type-checks, and we see that the problem with the [Cons] case is that the pattern-bound variable [idx'] does not have an apparent type compatible with [ls']. We need to use [match] annotations to make the relationship explicit. Unfortunately, the usual trick of postponing argument binding will not help us here. We need to match on both [ls] and [idx]; one or the other must be matched first. To get around this, we apply a trick that we will call "the convoy pattern," introducing a new function and applying it immediately, to satisfy the type checker.
80 84
81 [[ 85 [[
82 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A := 86 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A :=
83 match ls in ilist n return index n -> A with 87 match ls in ilist n return index n -> A with
94 | First _ => fun _ => x 98 | First _ => fun _ => x
95 | Next _ idx' => fun ls' => get ls' idx' 99 | Next _ idx' => fun ls' => get ls' idx'
96 end ls' 100 end ls'
97 end. 101 end.
98 102
103 ]]
104
99 There is just one problem left with this implementation. Though we know that the local [ls'] in the [Next] case is equal to the original [ls'], the type-checker is not satisfied that the recursive call to [get] does not introduce non-termination. We solve the problem by convoy-binding the partial application of [get] to [ls'], rather than [ls'] by itself. *) 105 There is just one problem left with this implementation. Though we know that the local [ls'] in the [Next] case is equal to the original [ls'], the type-checker is not satisfied that the recursive call to [get] does not introduce non-termination. We solve the problem by convoy-binding the partial application of [get] to [ls'], rather than [ls'] by itself. *)
100 106
101 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A := 107 Fixpoint get n (ls : ilist n) {struct ls} : index n -> A :=
102 match ls in ilist n return index n -> A with 108 match ls in ilist n return index n -> A with
103 | Nil => fun idx => 109 | Nil => fun idx =>
431 | inl _ => fst mls 437 | inl _ => fst mls
432 | inr idx' => fhget ls' (snd mls) idx' 438 | inr idx' => fhget ls' (snd mls) idx'
433 end 439 end
434 end. 440 end.
435 441
442 ]]
443
436 Only one problem remains. The expression [fst mls] is not known to have the proper type. To demonstrate that it does, we need to use the proof available in the [inl] case of the inner [match]. *) 444 Only one problem remains. The expression [fst mls] is not known to have the proper type. To demonstrate that it does, we need to use the proof available in the [inl] case of the inner [match]. *)
437 445
438 Fixpoint fhget (ls : list A) : fhlist ls -> fmember ls -> B elm := 446 Fixpoint fhget (ls : list A) : fhlist ls -> fmember ls -> B elm :=
439 match ls return fhlist ls -> fmember ls -> B elm with 447 match ls return fhlist ls -> fmember ls -> B elm with
440 | nil => fun _ idx => match idx with end 448 | nil => fun _ idx => match idx with end
539 (** [[ 547 (** [[
540 548
541 Inductive tree : Set := 549 Inductive tree : Set :=
542 | Leaf : A -> tree 550 | Leaf : A -> tree
543 | Node : forall n, filist tree n -> tree. 551 | Node : forall n, filist tree n -> tree.
552
553 ]]
544 554
545 [[ 555 [[
546 556
547 Error: Non strictly positive occurrence of "tree" in 557 Error: Non strictly positive occurrence of "tree" in
548 "forall n : nat, filist tree n -> tree" 558 "forall n : nat, filist tree n -> tree"