114 |
114 |
115 text{*Definition forms of @{text lfp_unfold} and @{text lfp_induct}, |
115 text{*Definition forms of @{text lfp_unfold} and @{text lfp_induct}, |
116 to control unfolding*} |
116 to control unfolding*} |
117 |
117 |
118 lemma def_lfp_unfold: "[| h==lfp(f); mono(f) |] ==> h = f(h)" |
118 lemma def_lfp_unfold: "[| h==lfp(f); mono(f) |] ==> h = f(h)" |
119 by (auto intro!: lfp_unfold) |
119 by (auto intro!: lfp_unfold) |
120 |
120 |
121 lemma def_lfp_induct: |
121 lemma def_lfp_induct: |
122 "[| A == lfp(f); mono(f); |
122 "[| A == lfp(f); mono(f); |
123 f (inf A P) \<le> P |
123 f (inf A P) \<le> P |
124 |] ==> A \<le> P" |
124 |] ==> A \<le> P" |
158 |
158 |
159 subsection {* Coinduction rules for greatest fixed points *} |
159 subsection {* Coinduction rules for greatest fixed points *} |
160 |
160 |
161 text{*weak version*} |
161 text{*weak version*} |
162 lemma weak_coinduct: "[| a: X; X \<subseteq> f(X) |] ==> a : gfp(f)" |
162 lemma weak_coinduct: "[| a: X; X \<subseteq> f(X) |] ==> a : gfp(f)" |
163 by (rule gfp_upperbound [THEN subsetD], auto) |
163 by (rule gfp_upperbound [THEN subsetD]) auto |
164 |
164 |
165 lemma weak_coinduct_image: "!!X. [| a : X; g`X \<subseteq> f (g`X) |] ==> g a : gfp f" |
165 lemma weak_coinduct_image: "!!X. [| a : X; g`X \<subseteq> f (g`X) |] ==> g a : gfp f" |
166 apply (erule gfp_upperbound [THEN subsetD]) |
166 apply (erule gfp_upperbound [THEN subsetD]) |
167 apply (erule imageI) |
167 apply (erule imageI) |
168 done |
168 done |
169 |
169 |
170 lemma coinduct_lemma: |
170 lemma coinduct_lemma: |
171 "[| X \<le> f (sup X (gfp f)); mono f |] ==> sup X (gfp f) \<le> f (sup X (gfp f))" |
171 "[| X \<le> f (sup X (gfp f)); mono f |] ==> sup X (gfp f) \<le> f (sup X (gfp f))" |
172 apply (frule gfp_lemma2) |
172 apply (frule gfp_lemma2) |
173 apply (drule mono_sup) |
173 apply (drule mono_sup) |
180 apply assumption |
180 apply assumption |
181 done |
181 done |
182 |
182 |
183 text{*strong version, thanks to Coen and Frost*} |
183 text{*strong version, thanks to Coen and Frost*} |
184 lemma coinduct_set: "[| mono(f); a: X; X \<subseteq> f(X Un gfp(f)) |] ==> a : gfp(f)" |
184 lemma coinduct_set: "[| mono(f); a: X; X \<subseteq> f(X Un gfp(f)) |] ==> a : gfp(f)" |
185 by (blast intro: weak_coinduct [OF _ coinduct_lemma]) |
185 by (blast intro: weak_coinduct [OF _ coinduct_lemma]) |
186 |
186 |
187 lemma coinduct: "[| mono(f); X \<le> f (sup X (gfp f)) |] ==> X \<le> gfp(f)" |
187 lemma coinduct: "[| mono(f); X \<le> f (sup X (gfp f)) |] ==> X \<le> gfp(f)" |
188 apply (rule order_trans) |
188 apply (rule order_trans) |
189 apply (rule sup_ge1) |
189 apply (rule sup_ge1) |
190 apply (erule gfp_upperbound [OF coinduct_lemma]) |
190 apply (erule gfp_upperbound [OF coinduct_lemma]) |
191 apply assumption |
191 apply assumption |
192 done |
192 done |
193 |
193 |
194 lemma gfp_fun_UnI2: "[| mono(f); a: gfp(f) |] ==> a: f(X Un gfp(f))" |
194 lemma gfp_fun_UnI2: "[| mono(f); a: gfp(f) |] ==> a: f(X Un gfp(f))" |
195 by (blast dest: gfp_lemma2 mono_Un) |
195 by (blast dest: gfp_lemma2 mono_Un) |
196 |
196 |
197 |
197 |
198 subsection {* Even Stronger Coinduction Rule, by Martin Coen *} |
198 subsection {* Even Stronger Coinduction Rule, by Martin Coen *} |
199 |
199 |
200 text{* Weakens the condition @{term "X \<subseteq> f(X)"} to one expressed using both |
200 text{* Weakens the condition @{term "X \<subseteq> f(X)"} to one expressed using both |
225 |
225 |
226 text{*Definition forms of @{text gfp_unfold} and @{text coinduct}, |
226 text{*Definition forms of @{text gfp_unfold} and @{text coinduct}, |
227 to control unfolding*} |
227 to control unfolding*} |
228 |
228 |
229 lemma def_gfp_unfold: "[| A==gfp(f); mono(f) |] ==> A = f(A)" |
229 lemma def_gfp_unfold: "[| A==gfp(f); mono(f) |] ==> A = f(A)" |
230 by (auto intro!: gfp_unfold) |
230 by (auto intro!: gfp_unfold) |
231 |
231 |
232 lemma def_coinduct: |
232 lemma def_coinduct: |
233 "[| A==gfp(f); mono(f); X \<le> f(sup X A) |] ==> X \<le> A" |
233 "[| A==gfp(f); mono(f); X \<le> f(sup X A) |] ==> X \<le> A" |
234 by (iprover intro!: coinduct) |
234 by (iprover intro!: coinduct) |
235 |
235 |
236 lemma def_coinduct_set: |
236 lemma def_coinduct_set: |
237 "[| A==gfp(f); mono(f); a:X; X \<subseteq> f(X Un A) |] ==> a: A" |
237 "[| A==gfp(f); mono(f); a:X; X \<subseteq> f(X Un A) |] ==> a: A" |
238 by (auto intro!: coinduct_set) |
238 by (auto intro!: coinduct_set) |
239 |
239 |
240 (*The version used in the induction/coinduction package*) |
240 (*The version used in the induction/coinduction package*) |
241 lemma def_Collect_coinduct: |
241 lemma def_Collect_coinduct: |
242 "[| A == gfp(%w. Collect(P(w))); mono(%w. Collect(P(w))); |
242 "[| A == gfp(%w. Collect(P(w))); mono(%w. Collect(P(w))); |
243 a: X; !!z. z: X ==> P (X Un A) z |] ==> |
243 a: X; !!z. z: X ==> P (X Un A) z |] ==> |
244 a : A" |
244 a : A" |
245 apply (erule def_coinduct_set, auto) |
245 by (erule def_coinduct_set) auto |
246 done |
|
247 |
246 |
248 lemma def_coinduct3: |
247 lemma def_coinduct3: |
249 "[| A==gfp(f); mono(f); a:X; X \<subseteq> f(lfp(%x. f(x) Un X Un A)) |] ==> a: A" |
248 "[| A==gfp(f); mono(f); a:X; X \<subseteq> f(lfp(%x. f(x) Un X Un A)) |] ==> a: A" |
250 by (auto intro!: coinduct3) |
249 by (auto intro!: coinduct3) |
251 |
250 |
252 text{*Monotonicity of @{term gfp}!*} |
251 text{*Monotonicity of @{term gfp}!*} |
253 lemma gfp_mono: "(!!Z. f Z \<le> g Z) ==> gfp f \<le> gfp g" |
252 lemma gfp_mono: "(!!Z. f Z \<le> g Z) ==> gfp f \<le> gfp g" |
254 by (rule gfp_upperbound [THEN gfp_least], blast intro: order_trans) |
253 by (rule gfp_upperbound [THEN gfp_least], blast intro: order_trans) |
255 |
254 |
294 |
293 |
295 parse_translation (advanced) {* |
294 parse_translation (advanced) {* |
296 let |
295 let |
297 fun fun_tr ctxt [cs] = |
296 fun fun_tr ctxt [cs] = |
298 let |
297 let |
299 (* FIXME proper name context!? *) |
298 val x = Syntax.free (fst (Name.variant "x" (Term.declare_term_frees cs Name.context))); |
300 val x = Free (singleton (Name.variant_list (Term.add_free_names cs [])) "x", dummyT); |
|
301 val ft = Datatype_Case.case_tr true ctxt [x, cs]; |
299 val ft = Datatype_Case.case_tr true ctxt [x, cs]; |
302 in lambda x ft end |
300 in lambda x ft end |
303 in [(@{syntax_const "_lam_pats_syntax"}, fun_tr)] end |
301 in [(@{syntax_const "_lam_pats_syntax"}, fun_tr)] end |
304 *} |
302 *} |
305 |
303 |