Mercurial > cpdt > repo
comparison src/Coinductive.v @ 281:4146889930c5
PC's Chapter 5 comments
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Fri, 15 Oct 2010 09:50:34 -0400 |
parents | c4b1c0de7af9 |
children | 2c88fc1dbe33 |
comparison
equal
deleted
inserted
replaced
280:15f49309c371 | 281:4146889930c5 |
---|---|
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: |
140 Variable f : A -> B. | 140 Variable f : A -> B. |
141 (* begin thide *) | 141 (* begin thide *) |
142 (** [[ | 142 (** [[ |
143 CoFixpoint map' (s : stream A) : stream B := | 143 CoFixpoint map' (s : stream A) : stream B := |
144 match s with | 144 match s with |
145 | Cons h t => interleave (Cons (f h) (map' s)) (Cons (f h) (map' s)) | 145 | Cons h t => interleave (Cons (f h) (map' t) (Cons (f h) (map' t)) |
146 end. | 146 end. |
147 | 147 |
148 ]] | 148 ]] |
149 | 149 |
150 We get another error message about an unguarded recursive call. This is because we are violating the second guardedness condition, which says that, not only must co-recursive calls be arguments to constructors, there must also %\textit{%#<i>#not be anything but [match]es and calls to constructors of the same co-inductive type#</i>#%}% wrapped around these immediate uses of co-recursive calls. The actual implemented rule for guardedness is a little more lenient than what we have just stated, but you can count on the illegality of any exception that would enhance the expressive power of co-recursion. | 150 We get another error message about an unguarded recursive call. This is because we are violating the second guardedness condition, which says that, not only must co-recursive calls be arguments to constructors, there must also %\textit{%#<i>#not be anything but [match]es and calls to constructors of the same co-inductive type#</i>#%}% wrapped around these immediate uses of co-recursive calls. The actual implemented rule for guardedness is a little more lenient than what we have just stated, but you can count on the illegality of any exception that would enhance the expressive power of co-recursion. |
151 | 151 |
152 Why enforce a rule like this? Imagine that, instead of [interleave], we had called some other, less well-behaved function on streams. Perhaps this other function might be defined mutually with [map']. It might deconstruct its first argument, retrieving [map' s] from within [Cons (f h) (map' s)]. Next it might try a [match] on this retrieved value, which amounts to deconstructing [map' s]. To figure out how this [match] turns out, we need to know the top-level structure of [map' s], but this is exactly what we started out trying to determine! We run into a loop in the evaluation process, and we have reached a witness of inconsistency if we are evaluating [approx (map' s) 1] for any [s]. *) | 152 Why enforce a rule like this? Imagine that, instead of [interleave], we had called some other, less well-behaved function on streams. Perhaps this other function might be defined mutually with [map']. It might deconstruct its first argument, retrieving [map' t] from within [Cons (f h) (map' t)]. Next it might try a [match] on this retrieved value, which amounts to deconstructing [map' t]. To figure out how this [match] turns out, we need to know the top-level structure of [map' t], but this is exactly what we started out trying to determine! We run into a loop in the evaluation process, and we have reached a witness of inconsistency if we are evaluating [approx (map' s) 1] for any [s]. *) |
153 (* end thide *) | 153 (* end thide *) |
154 | 154 |
155 End map'. | 155 End map'. |
156 | 156 |
157 | 157 |
231 | 231 |
232 ]] | 232 ]] |
233 | 233 |
234 Running [Guarded] here gives us the same error message that we got when we tried to run [Qed]. In larger proofs, [Guarded] can be helpful in detecting problems %\textit{%#<i>#before#</i>#%}% we think we are ready to run [Qed]. | 234 Running [Guarded] here gives us the same error message that we got when we tried to run [Qed]. In larger proofs, [Guarded] can be helpful in detecting problems %\textit{%#<i>#before#</i>#%}% we think we are ready to run [Qed]. |
235 | 235 |
236 We need to start the co-induction by applying one of [stream_eq]'s constructors. To do that, we need to know that both arguments to the predicate are [Cons]es. Informally, this is trivial, but [simpl] is not able to help us. *) | 236 We need to start the co-induction by applying [stream_eq]'s constructor. To do that, we need to know that both arguments to the predicate are [Cons]es. Informally, this is trivial, but [simpl] is not able to help us. *) |
237 | 237 |
238 Undo. | 238 Undo. |
239 simpl. | 239 simpl. |
240 (** [[ | 240 (** [[ |
241 ones_eq : stream_eq ones ones' | 241 ones_eq : stream_eq ones ones' |
346 | Imm : reg -> nat -> instr | 346 | Imm : reg -> nat -> instr |
347 | Copy : reg -> reg -> instr | 347 | Copy : reg -> reg -> instr |
348 | Jmp : label -> instr | 348 | Jmp : label -> instr |
349 | Jnz : reg -> label -> instr. | 349 | Jnz : reg -> label -> instr. |
350 | 350 |
351 (** We define a type [regs] of maps from registers to values. To define a function [set] for setting a register's value in a map, we import the [Arith] module from Coq's standard library, and we use its function [eq_nat_dec] for comparing natural numbers. *) | 351 (** We define a type [regs] of maps from registers to values. To define a function [set] for setting a register's value in a map, we import the [Arith] module from Coq's standard library, and we use its function [beq_nat] for comparing natural numbers. *) |
352 | 352 |
353 Definition regs := reg -> nat. | 353 Definition regs := reg -> nat. |
354 Require Import Arith. | 354 Require Import Arith. |
355 Definition set (rs : regs) (r : reg) (v : nat) : regs := | 355 Definition set (rs : regs) (r : reg) (v : nat) : regs := |
356 fun r' => if eq_nat_dec r r' then v else rs r'. | 356 fun r' => if beq_nat r r' then v else rs r'. |
357 | 357 |
358 (** An inductive [exec] judgment captures the effect of an instruction on the program counter and register bank. *) | 358 (** An inductive [exec] judgment captures the effect of an instruction on the program counter and register bank. *) |
359 | 359 |
360 Inductive exec : label -> regs -> instr -> label -> regs -> Prop := | 360 Inductive exec : label -> regs -> instr -> label -> regs -> Prop := |
361 | E_Imm : forall pc rs r n, exec pc rs (Imm r n) (S pc) (set rs r n) | 361 | E_Imm : forall pc rs r n, exec pc rs (Imm r n) (S pc) (set rs r n) |
374 match goal with | 374 match goal with |
375 | [ |- context[Jnz ?r _] ] => case_eq (rs r) | 375 | [ |- context[Jnz ?r _] ] => case_eq (rs r) |
376 end; eauto. | 376 end; eauto. |
377 Qed. | 377 Qed. |
378 | 378 |
379 (** We are ready to define a co-inductive judgment capturing the idea that a program runs forever. We define the judgment in terms of a program [prog], represented as a function mapping each label to the instruction found there. *) | 379 (** We are ready to define a co-inductive judgment capturing the idea that a program runs forever. We define the judgment in terms of a program [prog], represented as a function mapping each label to the instruction found there. That is, to simplify the proof, we consider only infinitely-long programs. *) |
380 | 380 |
381 Section safe. | 381 Section safe. |
382 Variable prog : label -> instr. | 382 Variable prog : label -> instr. |
383 | 383 |
384 CoInductive safe : label -> regs -> Prop := | 384 CoInductive safe : label -> regs -> Prop := |