1 (* Title: HOLCF/Tools/domain/domain_theorems.ML
3 Author: David von Oheimb
4 New proofs/tactics by Brian Huffman
6 Proof generator for domain command.
9 val HOLCF_ss = @{simpset};
11 structure Domain_Theorems = struct
13 val quiet_mode = ref false;
14 val trace_domain = ref false;
16 fun message s = if !quiet_mode then () else writeln s;
17 fun trace s = if !trace_domain then tracing s else ();
21 val adm_impl_admw = @{thm adm_impl_admw};
22 val adm_all = @{thm adm_all};
23 val adm_conj = @{thm adm_conj};
24 val adm_subst = @{thm adm_subst};
25 val antisym_less_inverse = @{thm antisym_less_inverse};
26 val beta_cfun = @{thm beta_cfun};
27 val cfun_arg_cong = @{thm cfun_arg_cong};
28 val ch2ch_Rep_CFunL = @{thm ch2ch_Rep_CFunL};
29 val ch2ch_Rep_CFunR = @{thm ch2ch_Rep_CFunR};
30 val chain_iterate = @{thm chain_iterate};
31 val compact_ONE = @{thm compact_ONE};
32 val compact_sinl = @{thm compact_sinl};
33 val compact_sinr = @{thm compact_sinr};
34 val compact_spair = @{thm compact_spair};
35 val compact_up = @{thm compact_up};
36 val contlub_cfun_arg = @{thm contlub_cfun_arg};
37 val contlub_cfun_fun = @{thm contlub_cfun_fun};
38 val fix_def2 = @{thm fix_def2};
39 val injection_eq = @{thm injection_eq};
40 val injection_less = @{thm injection_less};
41 val lub_equal = @{thm lub_equal};
42 val monofun_cfun_arg = @{thm monofun_cfun_arg};
43 val retraction_strict = @{thm retraction_strict};
44 val spair_eq = @{thm spair_eq};
45 val spair_less = @{thm spair_less};
46 val sscase1 = @{thm sscase1};
47 val ssplit1 = @{thm ssplit1};
48 val strictify1 = @{thm strictify1};
49 val wfix_ind = @{thm wfix_ind};
51 val iso_intro = @{thm iso.intro};
52 val iso_abs_iso = @{thm iso.abs_iso};
53 val iso_rep_iso = @{thm iso.rep_iso};
54 val iso_abs_strict = @{thm iso.abs_strict};
55 val iso_rep_strict = @{thm iso.rep_strict};
56 val iso_abs_defin' = @{thm iso.abs_defin'};
57 val iso_rep_defin' = @{thm iso.rep_defin'};
58 val iso_abs_defined = @{thm iso.abs_defined};
59 val iso_rep_defined = @{thm iso.rep_defined};
60 val iso_compact_abs = @{thm iso.compact_abs};
61 val iso_compact_rep = @{thm iso.compact_rep};
62 val iso_iso_swap = @{thm iso.iso_swap};
64 val exh_start = @{thm exh_start};
65 val ex_defined_iffs = @{thms ex_defined_iffs};
66 val exh_casedist0 = @{thm exh_casedist0};
67 val exh_casedists = @{thms exh_casedists};
82 (* ----- general proof facilities ------------------------------------------- *)
84 fun legacy_infer_term thy t =
85 let val ctxt = ProofContext.set_mode ProofContext.mode_schematic (ProofContext.init thy)
86 in singleton (Syntax.check_terms ctxt) (Sign.intern_term thy t) end;
88 fun pg'' thy defs t tacs =
90 val t' = legacy_infer_term thy t;
91 val asms = Logic.strip_imp_prems t';
92 val prop = Logic.strip_imp_concl t';
93 fun tac {prems, context} =
94 rewrite_goals_tac defs THEN
95 EVERY (tacs {prems = map (rewrite_rule defs) prems, context = context})
96 in Goal.prove_global thy [] asms prop tac end;
98 fun pg' thy defs t tacsf =
100 fun tacs {prems, context} =
101 if null prems then tacsf context
102 else cut_facts_tac prems 1 :: tacsf context;
103 in pg'' thy defs t tacs end;
105 fun case_UU_tac ctxt rews i v =
106 InductTacs.case_tac ctxt (v^"=UU") i THEN
107 asm_simp_tac (HOLCF_ss addsimps rews) i;
110 REPEAT_DETERM o resolve_tac
111 [chain_iterate, ch2ch_Rep_CFunR, ch2ch_Rep_CFunL];
113 (* ----- general proofs ----------------------------------------------------- *)
115 val all2E = @{lemma "!x y . P x y ==> (P x y ==> R) ==> R" by simp}
117 val dist_eqI = @{lemma "!!x::'a::po. ~ x << y ==> x ~= y" by (blast dest!: antisym_less_inverse)}
121 fun theorems (((dname, _), cons) : eq, eqs : eq list) thy =
124 val _ = message ("Proving isomorphism properties of domain "^dname^" ...");
127 (* ----- getting the axioms and definitions --------------------------------- *)
130 fun ga s dn = PureThy.get_thm thy (dn ^ "." ^ s);
132 val ax_abs_iso = ga "abs_iso" dname;
133 val ax_rep_iso = ga "rep_iso" dname;
134 val ax_when_def = ga "when_def" dname;
135 fun get_def mk_name (con,_) = ga (mk_name con^"_def") dname;
136 val axs_con_def = map (get_def extern_name) cons;
137 val axs_dis_def = map (get_def dis_name) cons;
138 val axs_mat_def = map (get_def mat_name) cons;
139 val axs_pat_def = map (get_def pat_name) cons;
142 fun def_of_sel sel = ga (sel^"_def") dname;
143 fun def_of_arg arg = Option.map def_of_sel (sel_of arg);
144 fun defs_of_con (_, args) = List.mapPartial def_of_arg args;
146 maps defs_of_con cons
148 val ax_copy_def = ga "copy_def" dname;
151 (* ----- theorems concerning the isomorphism -------------------------------- *)
153 val dc_abs = %%:(dname^"_abs");
154 val dc_rep = %%:(dname^"_rep");
155 val dc_copy = %%:(dname^"_copy");
158 val iso_locale = iso_intro OF [ax_abs_iso, ax_rep_iso];
159 val abs_strict = ax_rep_iso RS (allI RS retraction_strict);
160 val rep_strict = ax_abs_iso RS (allI RS retraction_strict);
161 val abs_defin' = iso_locale RS iso_abs_defin';
162 val rep_defin' = iso_locale RS iso_rep_defin';
163 val iso_rews = map standard [ax_abs_iso,ax_rep_iso,abs_strict,rep_strict];
165 (* ----- generating beta reduction rules from definitions-------------------- *)
167 val _ = trace " Proving beta reduction rules...";
170 fun arglist (Const _ $ Abs (s, _, t)) =
172 val (vars,body) = arglist t;
173 in (s :: vars, body) end
174 | arglist t = ([], t);
175 fun bind_fun vars t = Library.foldr mk_All (vars, t);
176 fun bound_vars 0 = []
177 | bound_vars i = Bound (i-1) :: bound_vars (i - 1);
179 fun appl_of_def def =
181 val (_ $ con $ lam) = concl_of def;
182 val (vars, rhs) = arglist lam;
183 val lhs = list_ccomb (con, bound_vars (length vars));
184 val appl = bind_fun vars (lhs == rhs);
185 val cs = ContProc.cont_thms lam;
186 val betas = map (fn c => mk_meta_eq (c RS beta_cfun)) cs;
187 in pg (def::betas) appl (K [rtac reflexive_thm 1]) end;
190 val _ = trace "Proving when_appl...";
191 val when_appl = appl_of_def ax_when_def;
192 val _ = trace "Proving con_appls...";
193 val con_appls = map appl_of_def axs_con_def;
197 let val t = TVar (("'a", n), pcpoS)
198 in (n + 1, if is_lazy arg then mk_uT t else t) end;
200 fun args2typ n [] = (n, oneT)
201 | args2typ n [arg] = arg2typ n arg
202 | args2typ n (arg::args) =
204 val (n1, t1) = arg2typ n arg;
205 val (n2, t2) = args2typ n1 args
206 in (n2, mk_sprodT (t1, t2)) end;
208 fun cons2typ n [] = (n,oneT)
209 | cons2typ n [con] = args2typ n (snd con)
210 | cons2typ n (con::cons) =
212 val (n1, t1) = args2typ n (snd con);
213 val (n2, t2) = cons2typ n1 cons
214 in (n2, mk_ssumT (t1, t2)) end;
216 fun cons2ctyp cons = ctyp_of thy (snd (cons2typ 1 cons));
220 val iso_swap = iso_locale RS iso_iso_swap;
221 fun one_con (con, args) =
223 val vns = map vname args;
224 val eqn = %:x_name === con_app2 con %: vns;
225 val conj = foldr1 mk_conj (eqn :: map (defined o %:) (nonlazy args));
226 in Library.foldr mk_ex (vns, conj) end;
228 val conj_assoc = @{thm conj_assoc};
229 val exh = foldr1 mk_disj ((%:x_name === UU) :: map one_con cons);
230 val thm1 = instantiate' [SOME (cons2ctyp cons)] [] exh_start;
231 val thm2 = rewrite_rule (map mk_meta_eq ex_defined_iffs) thm1;
232 val thm3 = rewrite_rule [mk_meta_eq @{thm conj_assoc}] thm2;
234 (* first 3 rules replace "x = UU \/ P" with "rep$x = UU \/ P" *)
237 etac (rep_defin' RS disjI1) 2,
239 rewrite_goals_tac [mk_meta_eq iso_swap],
242 val _ = trace " Proving exhaust...";
243 val exhaust = pg con_appls (mk_trp exh) (K tacs);
244 val _ = trace " Proving casedist...";
246 standard (rewrite_rule exh_casedists (exhaust RS exh_casedist0));
250 fun bind_fun t = Library.foldr mk_All (when_funs cons, t);
251 fun bound_fun i _ = Bound (length cons - i);
252 val when_app = list_ccomb (%%:(dname^"_when"), mapn bound_fun 1 cons);
254 val _ = trace " Proving when_strict...";
257 val axs = [when_appl, mk_meta_eq rep_strict];
258 val goal = bind_fun (mk_trp (strict when_app));
259 val tacs = [resolve_tac [sscase1, ssplit1, strictify1] 1];
260 in pg axs goal (K tacs) end;
262 val _ = trace " Proving when_apps...";
265 fun one_when n (con,args) =
267 val axs = when_appl :: con_appls;
268 val goal = bind_fun (lift_defined %: (nonlazy args,
269 mk_trp (when_app`(con_app con args) ===
270 list_ccomb (bound_fun n 0, map %# args))));
271 val tacs = [asm_simp_tac (HOLCF_ss addsimps [ax_abs_iso]) 1];
272 in pg axs goal (K tacs) end;
273 in mapn one_when 1 cons end;
275 val when_rews = when_strict :: when_apps;
277 (* ----- theorems concerning the constructors, discriminators and selectors - *)
280 fun dis_strict (con, _) =
282 val goal = mk_trp (strict (%%:(dis_name con)));
283 in pg axs_dis_def goal (K [rtac when_strict 1]) end;
285 fun dis_app c (con, args) =
287 val lhs = %%:(dis_name c) ` con_app con args;
288 val rhs = if con = c then TT else FF;
289 val goal = lift_defined %: (nonlazy args, mk_trp (lhs === rhs));
290 val tacs = [asm_simp_tac (HOLCF_ss addsimps when_rews) 1];
291 in pg axs_dis_def goal (K tacs) end;
293 val _ = trace " Proving dis_apps...";
294 val dis_apps = maps (fn (c,_) => map (dis_app c) cons) cons;
296 fun dis_defin (con, args) =
298 val goal = defined (%:x_name) ==> defined (%%:(dis_name con) `% x_name);
302 DETERM_UNTIL_SOLVED (CHANGED
303 (asm_simp_tac (HOLCF_ss addsimps dis_apps) 1))];
304 in pg [] goal (K tacs) end;
306 val _ = trace " Proving dis_stricts...";
307 val dis_stricts = map dis_strict cons;
308 val _ = trace " Proving dis_defins...";
309 val dis_defins = map dis_defin cons;
311 val dis_rews = dis_stricts @ dis_defins @ dis_apps;
315 fun mat_strict (con, _) =
317 val goal = mk_trp (strict (%%:(mat_name con)));
318 val tacs = [rtac when_strict 1];
319 in pg axs_mat_def goal (K tacs) end;
321 val _ = trace " Proving mat_stricts...";
322 val mat_stricts = map mat_strict cons;
324 fun one_mat c (con, args) =
326 val lhs = %%:(mat_name c) ` con_app con args;
329 then mk_return (mk_ctuple (map %# args))
331 val goal = lift_defined %: (nonlazy args, mk_trp (lhs === rhs));
332 val tacs = [asm_simp_tac (HOLCF_ss addsimps when_rews) 1];
333 in pg axs_mat_def goal (K tacs) end;
335 val _ = trace " Proving mat_apps...";
337 maps (fn (c,_) => map (one_mat c) cons) cons;
339 val mat_rews = mat_stricts @ mat_apps;
343 fun ps args = mapn (fn n => fn _ => %:("pat" ^ string_of_int n)) 1 args;
345 fun pat_lhs (con,args) = mk_branch (list_comb (%%:(pat_name con), ps args));
347 fun pat_rhs (con,[]) = mk_return ((%:"rhs") ` HOLogic.unit)
348 | pat_rhs (con,args) =
349 (mk_branch (mk_ctuple_pat (ps args)))
350 `(%:"rhs")`(mk_ctuple (map %# args));
354 val axs = @{thm branch_def} :: axs_pat_def;
355 val goal = mk_trp (strict (pat_lhs c ` (%:"rhs")));
356 val tacs = [simp_tac (HOLCF_ss addsimps [when_strict]) 1];
357 in pg axs goal (K tacs) end;
359 fun pat_app c (con, args) =
361 val axs = @{thm branch_def} :: axs_pat_def;
362 val lhs = (pat_lhs c)`(%:"rhs")`(con_app con args);
363 val rhs = if con = fst c then pat_rhs c else mk_fail;
364 val goal = lift_defined %: (nonlazy args, mk_trp (lhs === rhs));
365 val tacs = [asm_simp_tac (HOLCF_ss addsimps when_rews) 1];
366 in pg axs goal (K tacs) end;
368 val _ = trace " Proving pat_stricts...";
369 val pat_stricts = map pat_strict cons;
370 val _ = trace " Proving pat_apps...";
371 val pat_apps = maps (fn c => map (pat_app c) cons) cons;
373 val pat_rews = pat_stricts @ pat_apps;
377 val rev_contrapos = @{thm rev_contrapos};
378 fun con_strict (con, args) =
382 fun f arg = if vname arg = vn then UU else %# arg;
383 val goal = mk_trp (con_app2 con f args === UU);
384 val tacs = [asm_simp_tac (HOLCF_ss addsimps [abs_strict]) 1];
385 in pg con_appls goal (K tacs) end;
386 in map one_strict (nonlazy args) end;
388 fun con_defin (con, args) =
390 val concl = mk_trp (defined (con_app con args));
391 val goal = lift_defined %: (nonlazy args, concl);
393 rtac @{thm rev_contrapos} 1,
394 eres_inst_tac ctxt [(("f", 0), dis_name con)] cfun_arg_cong 1,
395 asm_simp_tac (HOLCF_ss addsimps dis_rews) 1];
396 in pg [] goal tacs end;
398 val _ = trace " Proving con_stricts...";
399 val con_stricts = maps con_strict cons;
400 val _ = trace " Proving pat_defins...";
401 val con_defins = map con_defin cons;
402 val con_rews = con_stricts @ con_defins;
407 [compact_sinl, compact_sinr, compact_spair, compact_up, compact_ONE];
408 fun con_compact (con, args) =
410 val concl = mk_trp (mk_compact (con_app con args));
411 val goal = lift (fn x => mk_compact (%#x)) (args, concl);
413 rtac (iso_locale RS iso_compact_abs) 1,
414 REPEAT (resolve_tac rules 1 ORELSE atac 1)];
415 in pg con_appls goal (K tacs) end;
417 val _ = trace " Proving con_compacts...";
418 val con_compacts = map con_compact cons;
423 pg axs_sel_def (mk_trp (strict (%%:sel)))
424 (K [simp_tac (HOLCF_ss addsimps when_rews) 1]);
426 fun sel_strict (_, args) =
427 List.mapPartial (Option.map one_sel o sel_of) args;
429 val _ = trace " Proving sel_stricts...";
430 val sel_stricts = maps sel_strict cons;
434 fun sel_app_same c n sel (con, args) =
436 val nlas = nonlazy args;
437 val vns = map vname args;
438 val vnn = List.nth (vns, n);
439 val nlas' = List.filter (fn v => v <> vnn) nlas;
440 val lhs = (%%:sel)`(con_app con args);
441 val goal = lift_defined %: (nlas', mk_trp (lhs === %:vnn));
444 then [case_UU_tac ctxt (when_rews @ con_stricts) 1 vnn]
446 val tacs2 = [asm_simp_tac (HOLCF_ss addsimps when_rews) 1];
447 in pg axs_sel_def goal (fn ctxt => (tacs1 ctxt @ tacs2)) end;
449 fun sel_app_diff c n sel (con, args) =
451 val nlas = nonlazy args;
452 val goal = mk_trp (%%:sel ` con_app con args === UU);
453 fun tacs1 ctxt = map (case_UU_tac ctxt (when_rews @ con_stricts) 1) nlas;
454 val tacs2 = [asm_simp_tac (HOLCF_ss addsimps when_rews) 1];
455 in pg axs_sel_def goal (fn ctxt => (tacs1 ctxt @ tacs2)) end;
457 fun sel_app c n sel (con, args) =
459 then sel_app_same c n sel (con, args)
460 else sel_app_diff c n sel (con, args);
462 fun one_sel c n sel = map (sel_app c n sel) cons;
463 fun one_sel' c n arg = Option.map (one_sel c n) (sel_of arg);
464 fun one_con (c, args) =
465 flat (map_filter I (mapn (one_sel' c) 0 args));
467 val _ = trace " Proving sel_apps...";
468 val sel_apps = maps one_con cons;
474 val goal = defined (%:x_name) ==> defined (%%:sel`%x_name);
478 DETERM_UNTIL_SOLVED (CHANGED
479 (asm_simp_tac (HOLCF_ss addsimps sel_apps) 1))];
480 in pg [] goal (K tacs) end;
482 val _ = trace " Proving sel_defins...";
485 then List.mapPartial (fn arg => Option.map sel_defin (sel_of arg))
486 (filter_out is_lazy (snd (hd cons)))
490 val sel_rews = sel_stricts @ sel_defins @ sel_apps;
491 val rev_contrapos = @{thm rev_contrapos};
493 val _ = trace " Proving dist_les...";
496 fun dist (con1, args1) (con2, args2) =
498 val goal = lift_defined %: (nonlazy args1,
499 mk_trp (con_app con1 args1 ~<< con_app con2 args2));
501 rtac @{thm rev_contrapos} 1,
502 eres_inst_tac ctxt [(("f", 0), dis_name con1)] monofun_cfun_arg 1]
503 @ map (case_UU_tac ctxt (con_stricts @ dis_rews) 1) (nonlazy args2)
504 @ [asm_simp_tac (HOLCF_ss addsimps dis_rews) 1];
505 in pg [] goal tacs end;
507 fun distinct (con1, args1) (con2, args2) =
509 val arg1 = (con1, args1);
511 (con2, ListPair.map (fn (arg,vn) => upd_vname (K vn) arg)
512 (args2, Name.variant_list (map vname args1) (map vname args2)));
513 in [dist arg1 arg2, dist arg2 arg1] end;
514 fun distincts [] = []
515 | distincts (c::cs) = (map (distinct c) cs) :: distincts cs;
516 in distincts cons end;
517 val dist_les = flat (flat distincts_le);
519 val _ = trace " Proving dist_eqs...";
522 fun distinct (_,args1) ((_,args2), leqs) =
524 val (le1,le2) = (hd leqs, hd(tl leqs));
525 val (eq1,eq2) = (le1 RS dist_eqI, le2 RS dist_eqI)
527 if nonlazy args1 = [] then [eq1, eq1 RS not_sym] else
528 if nonlazy args2 = [] then [eq2, eq2 RS not_sym] else
531 fun distincts [] = []
532 | distincts ((c,leqs)::cs) = flat
533 (ListPair.map (distinct c) ((map #1 cs),leqs)) @
535 in map standard (distincts (cons ~~ distincts_le)) end;
538 fun pgterm rel con args =
540 fun append s = upd_vname (fn v => v^s);
541 val (largs, rargs) = (args, map (append "'") args);
543 foldr1 mk_conj (ListPair.map rel (map %# largs, map %# rargs));
544 val prem = rel (con_app con largs, con_app con rargs);
545 val sargs = case largs of [_] => [] | _ => nonlazy args;
546 val prop = lift_defined %: (sargs, mk_trp (prem === concl));
547 in pg con_appls prop end;
548 val cons' = List.filter (fn (_,args) => args<>[]) cons;
550 val _ = trace " Proving inverts...";
553 val abs_less = ax_abs_iso RS (allI RS injection_less);
555 [asm_full_simp_tac (HOLCF_ss addsimps [abs_less, spair_less]) 1];
556 in map (fn (con, args) => pgterm (op <<) con args (K tacs)) cons' end;
558 val _ = trace " Proving injects...";
561 val abs_eq = ax_abs_iso RS (allI RS injection_eq);
562 val tacs = [asm_full_simp_tac (HOLCF_ss addsimps [abs_eq, spair_eq]) 1];
563 in map (fn (con, args) => pgterm (op ===) con args (K tacs)) cons' end;
566 (* ----- theorems concerning one induction step ----------------------------- *)
570 val goal = mk_trp (strict (dc_copy `% "f"));
571 val tacs = [asm_simp_tac (HOLCF_ss addsimps [abs_strict, when_strict]) 1];
572 in pg [ax_copy_def] goal (K tacs) end;
575 fun copy_app (con, args) =
577 val lhs = dc_copy`%"f"`(con_app con args);
578 val rhs = con_app2 con (app_rec_arg (cproj (%:"f") eqs)) args;
579 val goal = lift_defined %: (nonlazy_rec args, mk_trp (lhs === rhs));
580 val args' = List.filter (fn a => not (is_rec a orelse is_lazy a)) args;
581 val stricts = abs_strict::when_strict::con_stricts;
582 fun tacs1 ctxt = map (case_UU_tac ctxt stricts 1 o vname) args';
583 val tacs2 = [asm_simp_tac (HOLCF_ss addsimps when_apps) 1];
584 in pg [ax_copy_def] goal (fn ctxt => (tacs1 ctxt @ tacs2)) end;
586 val _ = trace " Proving copy_apps...";
587 val copy_apps = map copy_app cons;
591 fun one_strict (con, args) =
593 val goal = mk_trp (dc_copy`UU`(con_app con args) === UU);
594 val rews = copy_strict :: copy_apps @ con_rews;
595 fun tacs ctxt = map (case_UU_tac ctxt rews 1) (nonlazy args) @
596 [asm_simp_tac (HOLCF_ss addsimps rews) 1];
597 in pg [] goal tacs end;
599 fun has_nonlazy_rec (_, args) = exists is_nonlazy_rec args;
601 val _ = trace " Proving copy_stricts...";
602 val copy_stricts = map one_strict (List.filter has_nonlazy_rec cons);
605 val copy_rews = copy_strict :: copy_apps @ copy_stricts;
609 |> Sign.add_path (Long_Name.base_name dname)
610 |> (snd o PureThy.add_thmss [
611 ((Binding.name "iso_rews" , iso_rews ), [Simplifier.simp_add]),
612 ((Binding.name "exhaust" , [exhaust] ), []),
613 ((Binding.name "casedist" , [casedist]), [Induct.cases_type dname]),
614 ((Binding.name "when_rews", when_rews ), [Simplifier.simp_add]),
615 ((Binding.name "compacts", con_compacts), [Simplifier.simp_add]),
616 ((Binding.name "con_rews", con_rews), [Simplifier.simp_add]),
617 ((Binding.name "sel_rews", sel_rews), [Simplifier.simp_add]),
618 ((Binding.name "dis_rews", dis_rews), [Simplifier.simp_add]),
619 ((Binding.name "pat_rews", pat_rews), [Simplifier.simp_add]),
620 ((Binding.name "dist_les", dist_les), [Simplifier.simp_add]),
621 ((Binding.name "dist_eqs", dist_eqs), [Simplifier.simp_add]),
622 ((Binding.name "inverts" , inverts ), [Simplifier.simp_add]),
623 ((Binding.name "injects" , injects ), [Simplifier.simp_add]),
624 ((Binding.name "copy_rews", copy_rews), [Simplifier.simp_add]),
625 ((Binding.name "match_rews", mat_rews), [Simplifier.simp_add])
628 |> pair (iso_rews @ when_rews @ con_rews @ sel_rews @ dis_rews @
629 pat_rews @ dist_les @ dist_eqs @ copy_rews)
632 fun comp_theorems (comp_dnam, eqs: eq list) thy =
634 val global_ctxt = ProofContext.init thy;
636 val dnames = map (fst o fst) eqs;
637 val conss = map snd eqs;
638 val comp_dname = Sign.full_bname thy comp_dnam;
640 val _ = message ("Proving induction properties of domain "^comp_dname^" ...");
643 (* ----- getting the composite axiom and definitions ------------------------ *)
646 fun ga s dn = PureThy.get_thm thy (dn ^ "." ^ s);
648 val axs_reach = map (ga "reach" ) dnames;
649 val axs_take_def = map (ga "take_def" ) dnames;
650 val axs_finite_def = map (ga "finite_def") dnames;
651 val ax_copy2_def = ga "copy_def" comp_dnam;
652 val ax_bisim_def = ga "bisim_def" comp_dnam;
656 fun gt s dn = PureThy.get_thm thy (dn ^ "." ^ s);
657 fun gts s dn = PureThy.get_thms thy (dn ^ "." ^ s);
659 val cases = map (gt "casedist" ) dnames;
660 val con_rews = maps (gts "con_rews" ) dnames;
661 val copy_rews = maps (gts "copy_rews") dnames;
664 fun dc_take dn = %%:(dn^"_take");
665 val x_name = idx_name dnames "x";
666 val P_name = idx_name dnames "P";
667 val n_eqs = length eqs;
669 (* ----- theorems concerning finite approximation and finite induction ------ *)
672 val iterate_Cprod_ss = simpset_of @{theory Fix};
673 val copy_con_rews = copy_rews @ con_rews;
675 (if n_eqs = 1 then [] else [ax_copy2_def]) @ axs_take_def;
676 val _ = trace " Proving take_stricts...";
679 fun one_eq ((dn, args), _) = strict (dc_take dn $ %:"n");
680 val goal = mk_trp (foldr1 mk_conj (map one_eq eqs));
682 InductTacs.induct_tac ctxt [[SOME "n"]] 1,
683 simp_tac iterate_Cprod_ss 1,
684 asm_simp_tac (iterate_Cprod_ss addsimps copy_rews) 1];
685 in pg copy_take_defs goal tacs end;
687 val take_stricts' = rewrite_rule copy_take_defs take_stricts;
690 val goal = mk_trp ((dc_take dn $ %%:"HOL.zero") `% x_name n === UU);
691 in pg axs_take_def goal (K [simp_tac iterate_Cprod_ss 1]) end;
692 val take_0s = mapn take_0 1 dnames;
693 fun c_UU_tac ctxt = case_UU_tac ctxt (take_stricts'::copy_con_rews) 1;
694 val _ = trace " Proving take_apps...";
697 fun mk_eqn dn (con, args) =
699 fun mk_take n = dc_take (List.nth (dnames, n)) $ %:"n";
700 val lhs = (dc_take dn $ (%%:"Suc" $ %:"n"))`(con_app con args);
701 val rhs = con_app2 con (app_rec_arg mk_take) args;
702 in Library.foldr mk_all (map vname args, lhs === rhs) end;
703 fun mk_eqns ((dn, _), cons) = map (mk_eqn dn) cons;
704 val goal = mk_trp (foldr1 mk_conj (maps mk_eqns eqs));
705 val simps = List.filter (has_fewer_prems 1) copy_rews;
706 fun con_tac ctxt (con, args) =
707 if nonlazy_rec args = []
709 else EVERY (map (c_UU_tac ctxt) (nonlazy_rec args)) THEN
710 asm_full_simp_tac (HOLCF_ss addsimps copy_rews) 1;
711 fun eq_tacs ctxt ((dn, _), cons) = map (con_tac ctxt) cons;
713 simp_tac iterate_Cprod_ss 1 ::
714 InductTacs.induct_tac ctxt [[SOME "n"]] 1 ::
715 simp_tac (iterate_Cprod_ss addsimps copy_con_rews) 1 ::
716 asm_full_simp_tac (HOLCF_ss addsimps simps) 1 ::
717 TRY (safe_tac HOL_cs) ::
718 maps (eq_tacs ctxt) eqs;
719 in pg copy_take_defs goal tacs end;
721 val take_rews = map standard
722 (atomize global_ctxt take_stricts @ take_0s @ atomize global_ctxt take_apps);
726 fun one_con p (con,args) =
728 fun ind_hyp arg = %:(P_name (1 + rec_of arg)) $ bound_arg args arg;
729 val t1 = mk_trp (%:p $ con_app2 con (bound_arg args) args);
730 val t2 = lift ind_hyp (List.filter is_rec args, t1);
731 val t3 = lift_defined (bound_arg (map vname args)) (nonlazy args, t2);
732 in Library.foldr mk_All (map vname args, t3) end;
734 fun one_eq ((p, cons), concl) =
735 mk_trp (%:p $ UU) ===> Logic.list_implies (map (one_con p) cons, concl);
737 fun ind_term concf = Library.foldr one_eq
738 (mapn (fn n => fn x => (P_name n, x)) 1 conss,
739 mk_trp (foldr1 mk_conj (mapn concf 1 dnames)));
740 val take_ss = HOL_ss addsimps take_rews;
741 fun quant_tac ctxt i = EVERY
742 (mapn (fn n => fn _ => res_inst_tac ctxt [(("x", 0), x_name n)] spec i) 1 dnames);
744 fun ind_prems_tac prems = EVERY
746 (resolve_tac prems 1 ::
748 resolve_tac prems 1 ::
749 map (K(atac 1)) (nonlazy args) @
750 map (K(atac 1)) (List.filter is_rec args))
754 (* check whether every/exists constructor of the n-th part of the equation:
755 it has a possibly indirectly recursive argument that isn't/is possibly
757 fun rec_to quant nfn rfn ns lazy_rec (n,cons) = quant (exists (fn arg =>
758 is_rec arg andalso not(rec_of arg mem ns) andalso
759 ((rec_of arg = n andalso nfn(lazy_rec orelse is_lazy arg)) orelse
760 rec_of arg <> n andalso rec_to quant nfn rfn (rec_of arg::ns)
761 (lazy_rec orelse is_lazy arg) (n, (List.nth(conss,rec_of arg))))
763 fun all_rec_to ns = rec_to forall not all_rec_to ns;
765 if all_rec_to [] false (n,cons)
766 then (warning ("domain "^List.nth(dnames,n)^" is empty!"); true)
768 fun lazy_rec_to ns = rec_to exists I lazy_rec_to ns;
771 val n__eqs = mapn (fn n => fn (_,cons) => (n,cons)) 0 eqs;
772 val is_emptys = map warn n__eqs;
773 val is_finite = forall (not o lazy_rec_to [] false) n__eqs;
776 val _ = trace " Proving finite_ind...";
779 fun concf n dn = %:(P_name n) $ (dc_take dn $ %:"n" `%(x_name n));
780 val goal = ind_term concf;
782 fun tacf {prems, context} =
787 InductTacs.induct_tac context [[SOME "n"]] 1,
788 simp_tac (take_ss addsimps prems) 1,
789 TRY (safe_tac HOL_cs)];
791 case_UU_tac context (prems @ con_rews) 1
792 (List.nth (dnames, rec_of arg) ^ "_take n$" ^ vname arg);
793 fun con_tacs (con, args) =
794 asm_simp_tac take_ss 1 ::
795 map arg_tac (List.filter is_nonlazy_rec args) @
796 [resolve_tac prems 1] @
797 map (K (atac 1)) (nonlazy args) @
798 map (K (etac spec 1)) (List.filter is_rec args);
799 fun cases_tacs (cons, cases) =
800 res_inst_tac context [(("x", 0), "x")] cases 1 ::
801 asm_simp_tac (take_ss addsimps prems) 1 ::
804 tacs1 @ maps cases_tacs (conss ~~ cases)
806 in pg'' thy [] goal tacf end;
808 val _ = trace " Proving take_lemmas...";
811 fun take_lemma n (dn, ax_reach) =
813 val lhs = dc_take dn $ Bound 0 `%(x_name n);
814 val rhs = dc_take dn $ Bound 0 `%(x_name n^"'");
815 val concl = mk_trp (%:(x_name n) === %:(x_name n^"'"));
816 val goal = mk_All ("n", mk_trp (lhs === rhs)) ===> concl;
817 fun tacf {prems, context} = [
818 res_inst_tac context [(("t", 0), x_name n )] (ax_reach RS subst) 1,
819 res_inst_tac context [(("t", 0), x_name n^"'")] (ax_reach RS subst) 1,
822 (rtac (contlub_cfun_arg RS ssubst) 1 THEN chain_tac 1)),
823 stac contlub_cfun_fun 1,
824 stac contlub_cfun_fun 2,
828 resolve_tac prems 1];
829 in pg'' thy axs_take_def goal tacf end;
830 in mapn take_lemma 1 (dnames ~~ axs_reach) end;
832 (* ----- theorems concerning finiteness and induction ----------------------- *)
834 val _ = trace " Proving finites, ind...";
837 then (* finite case *)
839 fun take_enough dn = mk_ex ("n",dc_take dn $ Bound 0 ` %:"x" === %:"x");
842 val prem1 = mk_trp (defined (%:"x"));
843 val disj1 = mk_all ("n", dc_take dn $ Bound 0 ` %:"x" === UU);
844 val prem2 = mk_trp (mk_disj (disj1, take_enough dn));
845 val concl = mk_trp (take_enough dn);
846 val goal = prem1 ===> prem2 ===> concl;
850 resolve_tac take_lemmas 1,
851 asm_simp_tac take_ss 1,
853 in pg [] goal (K tacs) end;
854 val finite_lemmas1a = map dname_lemma dnames;
858 fun mk_eqn n ((dn, args), _) =
860 val disj1 = dc_take dn $ Bound 1 ` Bound 0 === UU;
861 val disj2 = dc_take dn $ Bound 1 ` Bound 0 === Bound 0;
864 (x_name n, Type (dn,args), mk_disj (disj1, disj2))
867 mk_trp (mk_all ("n", foldr1 mk_conj (mapn mk_eqn 1 eqs)));
868 fun arg_tacs ctxt vn = [
869 eres_inst_tac ctxt [(("x", 0), vn)] all_dupE 1,
871 asm_simp_tac (HOL_ss addsimps con_rews) 1,
872 asm_simp_tac take_ss 1];
873 fun con_tacs ctxt (con, args) =
874 asm_simp_tac take_ss 1 ::
875 maps (arg_tacs ctxt) (nonlazy_rec args);
876 fun foo_tacs ctxt n (cons, cases) =
877 simp_tac take_ss 1 ::
879 res_inst_tac ctxt [(("x", 0), x_name n)] cases 1 ::
880 asm_simp_tac take_ss 1 ::
881 maps (con_tacs ctxt) cons;
884 InductTacs.induct_tac ctxt [[SOME "n"]] 1 ::
885 simp_tac take_ss 1 ::
886 TRY (safe_tac (empty_cs addSEs [conjE] addSIs [conjI])) ::
887 flat (mapn (foo_tacs ctxt) 1 (conss ~~ cases));
888 in pg [] goal tacs end;
890 fun one_finite (dn, l1b) =
892 val goal = mk_trp (%%:(dn^"_finite") $ %:"x");
894 case_UU_tac ctxt take_rews 1 "x",
895 eresolve_tac finite_lemmas1a 1,
898 cut_facts_tac [l1b] 1,
900 in pg axs_finite_def goal tacs end;
902 val finites = map one_finite (dnames ~~ atomize global_ctxt finite_lemma1b);
905 fun concf n dn = %:(P_name n) $ %:(x_name n);
906 fun tacf {prems, context} =
908 fun finite_tacs (finite, fin_ind) = [
909 rtac(rewrite_rule axs_finite_def finite RS exE)1,
912 ind_prems_tac prems];
914 TRY (safe_tac HOL_cs) ::
915 maps finite_tacs (finites ~~ atomize global_ctxt finite_ind)
917 in pg'' thy [] (ind_term concf) tacf end;
918 in (finites, ind) end (* let *)
920 else (* infinite case *)
922 fun one_finite n dn =
923 read_instantiate global_ctxt [(("P", 0), dn ^ "_finite " ^ x_name n)] excluded_middle;
924 val finites = mapn one_finite 1 dnames;
928 fun one_adm n _ = mk_trp (mk_adm (%:(P_name n)));
929 fun concf n dn = %:(P_name n) $ %:(x_name n);
930 in Logic.list_implies (mapn one_adm 1 dnames, ind_term concf) end;
931 fun tacf {prems, context} =
932 map (fn ax_reach => rtac (ax_reach RS subst) 1) axs_reach @ [
934 rtac (adm_impl_admw RS wfix_ind) 1,
935 REPEAT_DETERM (rtac adm_all 1),
937 TRY (rtac adm_conj 1) THEN
938 rtac adm_subst 1 THEN
939 cont_tacR 1 THEN resolve_tac prems 1),
941 rtac (rewrite_rule axs_take_def finite_ind) 1,
942 ind_prems_tac prems];
943 val ind = (pg'' thy [] goal tacf
945 (warning "Cannot prove infinite induction rule"; refl));
946 in (finites, ind) end;
949 (* ----- theorem concerning coinduction ------------------------------------- *)
952 val xs = mapn (fn n => K (x_name n)) 1 dnames;
953 fun bnd_arg n i = Bound(2*(n_eqs - n)-i-1);
954 val take_ss = HOL_ss addsimps take_rews;
955 val sproj = prj (fn s => K("fst("^s^")")) (fn s => K("snd("^s^")"));
956 val _ = trace " Proving coind_lemma...";
959 fun mk_prj n _ = proj (%:"R") eqs n $ bnd_arg n 0 $ bnd_arg n 1;
961 (dc_take dn $ %:"n" ` bnd_arg n 0) ===
962 (dc_take dn $ %:"n" ` bnd_arg n 1);
963 fun mk_all2 (x,t) = mk_all (x, mk_all (x^"'", t));
965 mk_trp (mk_imp (%%:(comp_dname^"_bisim") $ %:"R",
966 Library.foldr mk_all2 (xs,
967 Library.foldr mk_imp (mapn mk_prj 0 dnames,
968 foldr1 mk_conj (mapn mk_eqn 0 dnames)))));
969 fun x_tacs ctxt n x = [
972 eres_inst_tac ctxt [(("P", 1), sproj "R" eqs n^" "^x^" "^x^"'")] (mp RS disjE) 1,
973 TRY (safe_tac HOL_cs),
974 REPEAT (CHANGED (asm_simp_tac take_ss 1))];
977 InductTacs.induct_tac ctxt [[SOME "n"]] 1,
980 flat (mapn (x_tacs ctxt) 0 xs);
981 in pg [ax_bisim_def] goal tacs end;
983 val _ = trace " Proving coind...";
986 fun mk_prj n x = mk_trp (proj (%:"R") eqs n $ %:x $ %:(x^"'"));
987 fun mk_eqn x = %:x === %:(x^"'");
989 mk_trp (%%:(comp_dname^"_bisim") $ %:"R") ===>
990 Logic.list_implies (mapn mk_prj 0 xs,
991 mk_trp (foldr1 mk_conj (map mk_eqn xs)));
993 TRY (safe_tac HOL_cs) ::
994 maps (fn take_lemma => [
996 cut_facts_tac [coind_lemma] 1,
999 in pg [] goal (K tacs) end;
1002 val inducts = ProjectRule.projections (ProofContext.init thy) ind;
1003 fun ind_rule (dname, rule) = ((Binding.empty, [rule]), [Induct.induct_type dname]);
1005 in thy |> Sign.add_path comp_dnam
1006 |> (snd o (PureThy.add_thmss (map (Thm.no_attributes o apfst Binding.name) [
1007 ("take_rews" , take_rews ),
1008 ("take_lemmas", take_lemmas),
1009 ("finites" , finites ),
1010 ("finite_ind", [finite_ind]),
1012 ("coind" , [coind ])])))
1013 |> (snd o (PureThy.add_thmss (map ind_rule (dnames ~~ inducts))))
1014 |> Sign.parent_path |> pair take_rews