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 :=