Skip to content

Commit fa6a824

Browse files
authored
Automate the corecursor (#97)
2 parents 8a4fa77 + 3883210 commit fa6a824

File tree

15 files changed

+3107
-1297
lines changed

15 files changed

+3107
-1297
lines changed

ROOT

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ session Tests in "tests" = Case_Studies +
4848
Case_Study_Regression_Tests
4949
Fixpoint_Tests
5050
Binder_Datatype_Tests
51+
Binder_Codatatype_Tests
5152

5253
session Case_Studies in "case_studies" = Binders +
5354
sessions

Tools/mrbnf_comp.ML

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,6 @@ fun seal_mrbnf qualify (unfold_set : unfold_set) b force_out_of_line Ds all_Ds m
13731373
the_default s (try (unsuffix "_pre") s)
13741374
) b);
13751375
val (class, lthy) = Var_Classes.mk_class_for_bound class_name mrbnf_bd' lthy;
1376-
val (coclass, lthy) = Var_Classes.mk_class_for_bound (Binding.prefix_name "co" class_name) (BNF_LFP_Util.mk_cardSuc mrbnf_bd') lthy;
13771376

13781377
fun subclass_tac ctxt = EVERY1 [
13791378
K (Local_Defs.unfold0_tac ctxt (no_reflexive [mrbnf_bd_def])),

Tools/mrbnf_corecursor.ML

Lines changed: 2024 additions & 0 deletions
Large diffs are not rendered by default.

Tools/mrbnf_fp.ML

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,20 @@ fun define_fp_consts fp_kind (models: mrbnf_fp_model list) (binding_relation : (
146146
val tsubst = Term.typ_subst_atomic subst;
147147
val subst = Term.subst_atomic_types subst;
148148
val ctr_sugar = #ctr_sugar (#fp_ctr_sugar sugar);
149+
val coinduct_sugar = the (#fp_co_induct_sugar sugar);
149150
in {
150151
T = tsubst (#T sugar),
151152
ctor = subst (hd (#ctrs ctr_sugar)),
152153
dtor = Option.map subst (try (hd o hd) (#selss ctr_sugar)),
153-
induct = hd (#common_co_inducts (the (#fp_co_induct_sugar sugar))),
154+
induct = hd (#common_co_inducts coinduct_sugar),
154155
inject = hd (#injects ctr_sugar),
155156
expand = try hd (#expands ctr_sugar),
156157
sel = try (hd o hd) (#sel_thmss ctr_sugar),
157158
exhaust = #exhaust ctr_sugar,
158159
case_t = subst (#casex ctr_sugar),
159-
case_thm = hd (#case_thms ctr_sugar)
160+
case_thm = hd (#case_thms ctr_sugar),
161+
corec = #co_rec coinduct_sugar,
162+
corec_def = #co_rec_thms coinduct_sugar
160163
} end
161164
) T_sugars, lthy) end;
162165

@@ -3629,7 +3632,13 @@ fun construct_binder_fp fp_kind models binding_relation lthy =
36293632
]);
36303633
in SOME {
36313634
existential_coinduct = existential_coinduct,
3632-
fresh_coinduct_param = fresh_coinduct_param
3635+
fresh_coinduct_param = fresh_coinduct_param,
3636+
corec = map #corec raw_Ts,
3637+
corec_def = flat (map #corec_def raw_Ts),
3638+
is_frees = map #preds is_freess,
3639+
is_free_induct = map #induct is_freess,
3640+
FVars_raw_defs = map (map snd) FVars_rawss,
3641+
coinduct = (#induct alphas)
36333642
} end
36343643

36353644
val fp_result = {

Tools/mrbnf_fp_def_sugar.ML

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,13 @@ sig
7474

7575
type greatest_fp_thms = {
7676
existential_coinduct: thm,
77-
fresh_coinduct_param: thm
77+
fresh_coinduct_param: thm,
78+
corec: term list,
79+
corec_def: thm list,
80+
is_frees: term list list,
81+
is_free_induct: thm list,
82+
FVars_raw_defs: thm list list,
83+
coinduct: thm
7884
};
7985

8086
type fp_result = {
@@ -251,12 +257,24 @@ fun morph_least_fp_thms phi ({ subshape_rel, subshapess, wf_subshape, set_subsha
251257

252258
type greatest_fp_thms = {
253259
existential_coinduct: thm,
254-
fresh_coinduct_param: thm
260+
fresh_coinduct_param: thm,
261+
corec: term list,
262+
corec_def: thm list,
263+
is_frees: term list list,
264+
is_free_induct: thm list,
265+
FVars_raw_defs: thm list list,
266+
coinduct: thm
255267
};
256268

257-
fun morph_greatest_fp_thms phi { existential_coinduct, fresh_coinduct_param } = {
269+
fun morph_greatest_fp_thms phi { existential_coinduct, fresh_coinduct_param, corec, corec_def, is_frees, is_free_induct, FVars_raw_defs, coinduct } = {
258270
existential_coinduct = Morphism.thm phi existential_coinduct,
259-
fresh_coinduct_param = Morphism.thm phi fresh_coinduct_param
271+
fresh_coinduct_param = Morphism.thm phi fresh_coinduct_param,
272+
corec = map (Morphism.term phi) corec,
273+
corec_def = map (Morphism.thm phi) corec_def,
274+
is_frees = map (map (Morphism.term phi)) is_frees,
275+
is_free_induct = map (Morphism.thm phi) is_free_induct,
276+
FVars_raw_defs = map (map (Morphism.thm phi)) FVars_raw_defs,
277+
coinduct = Morphism.thm phi coinduct
260278
}: greatest_fp_thms;
261279

262280
type fp_result = {
@@ -362,8 +380,10 @@ fun note_fp_result (fp_res : fp_result) lthy =
362380
("permute_raw_comp0s", [#permute_comp0 raw]),
363381
("permute_raw_comps", [#permute_comp raw]),
364382
("alpha_bij_eq", [#alpha_bij_eq (#inner raw)]),
383+
("alpha_bij_eq_inv", [#alpha_bij_eq_inv (#inner raw)]),
365384
("alpha_refl", [#alpha_refl (#inner raw)]),
366385
("FVars_raw_permute", #FVars_permutes raw),
386+
("permute_raw_simp", [#permute_ctor raw]),
367387
("permute_raw_id", [#permute_id raw])
368388
] else []);
369389

Tools/mrbnf_sugar.ML

Lines changed: 78 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type binder_sugar = {
1717
map_simps: thm list,
1818
set_simpss: thm list list,
1919
permute_simps: thm list,
20-
map_permute: thm,
20+
map_permute: thm option,
2121
subst_simps: thm list option,
2222
bsetss: term option list list,
2323
bset_bounds: thm list,
@@ -41,7 +41,7 @@ val register_binder_sugar: string -> binder_sugar -> local_theory -> local_theor
4141

4242
val create_binder_type : MRBNF_Util.fp_kind -> spec -> local_theory
4343
-> (MRBNF_FP_Def_Sugar.fp_result * typ * MRBNF_Def.mrbnf * MRBNF_Comp.absT_info) * local_theory
44-
val create_binder_datatype : spec -> local_theory -> binder_sugar * local_theory
44+
val create_binder_datatype : bool -> spec -> local_theory -> binder_sugar * local_theory
4545

4646
end
4747

@@ -71,7 +71,7 @@ type binder_sugar = {
7171
map_simps: thm list,
7272
set_simpss: thm list list,
7373
permute_simps: thm list,
74-
map_permute: thm,
74+
map_permute: thm option,
7575
subst_simps: thm list option,
7676
bsetss: term option list list,
7777
bset_bounds: thm list,
@@ -86,7 +86,7 @@ fun morph_binder_sugar phi { map_simps, permute_simps, map_permute, set_simpss,
8686
strong_induct, distinct, inject, ctors, bsetss, bset_bounds } = {
8787
map_simps = map (Morphism.thm phi) map_simps,
8888
permute_simps = map (Morphism.thm phi) permute_simps,
89-
map_permute = Morphism.thm phi map_permute,
89+
map_permute = Option.map (Morphism.thm phi) map_permute,
9090
set_simpss = map (map (Morphism.thm phi)) set_simpss,
9191
subst_simps = Option.map (map (Morphism.thm phi)) subst_simps,
9292
bsetss = map (map (Option.map (Morphism.term phi))) bsetss,
@@ -248,14 +248,22 @@ fun build_set_for _ aT x (TFree (s, _)) = if s = fst (dest_TFree aT) then SOME (
248248
end
249249
) (mr_bnf_of lthy false C);
250250

251-
fun create_binder_datatype (spec : spec) lthy =
251+
fun create_binder_datatype co (spec : spec) lthy =
252252
let
253-
val ((res, fp_pre_T, mrbnf, absinfo), lthy) = create_binder_type MRBNF_Util.Least_FP spec lthy;
253+
val fp_kind = if co then MRBNF_Util.Greatest_FP else MRBNF_Util.Least_FP;
254+
val ((res, fp_pre_T, mrbnf, absinfo), lthy) = create_binder_type fp_kind spec lthy;
254255

255-
val (recursor_result, lthy) = MRBNF_Recursor.create_binding_recursor I res lthy;
256+
val (vvsubst_res_opt, lthy) = if co then (NONE, lthy) else (* TODO: Automate renaming for codatatypes *)
257+
let
258+
val (recursor_result, lthy) = MRBNF_Recursor.create_binding_recursor I res lthy;
256259

257-
val ([(rec_mrbnf, vvsubst_res)], lthy) = MRBNF_VVSubst.mrbnf_of_quotient_fixpoint [#map_b spec] I res (#QREC_fixed recursor_result) lthy;
258-
val lthy = MRBNF_Def.register_mrbnf_raw (fst (dest_Type (#T (hd (#quotient_fps res))))) rec_mrbnf lthy;
260+
val ([(rec_mrbnf, vvsubst_res)], lthy) = MRBNF_VVSubst.mrbnf_of_quotient_fixpoint [#map_b spec] I res (#QREC_fixed recursor_result) lthy;
261+
val lthy = MRBNF_Def.register_mrbnf_raw (fst (dest_Type (#T (hd (#quotient_fps res))))) rec_mrbnf lthy;
262+
in (SOME {
263+
recursor_result = recursor_result,
264+
rec_mrbnf = rec_mrbnf,
265+
vvsubst_res = vvsubst_res
266+
}, lthy) end
259267

260268
val nrecs = fold (curry (op+)) (#rec_vars res) 0;
261269
val quotient_ctor = #ctor (hd (#quotient_fps res));
@@ -295,15 +303,15 @@ fun create_binder_datatype (spec : spec) lthy =
295303
val (vars, passives) = chop (length (#binding_rel spec)) vars;
296304

297305
val ((pfrees, plives), pbounds) = passives
298-
|> chop (MRBNF_Def.free_of_mrbnf rec_mrbnf - length vars)
299-
||>> chop (MRBNF_Def.live_of_mrbnf rec_mrbnf);
306+
|> chop (MRBNF_Def.free_of_mrbnf mrbnf - length vars)
307+
||>> chop (MRBNF_Def.live_of_mrbnf mrbnf - nrecs);
300308

301309
val (plives', _) = lthy
302310
|> fold_rev Variable.declare_typ (vars @ passives)
303311
|> mk_TFrees (length plives);
304312
val args' = fst (@{fold_map 2} (fn MRBNF_Def.Live_Var => K (fn xs => (hd xs, tl xs))
305313
| _ => fn x => fn xs => (x, xs)
306-
) (MRBNF_Def.var_types_of_mrbnf rec_mrbnf) (vars @ passives) plives');
314+
) (take (length (vars @ passives)) (MRBNF_Def.var_types_of_mrbnf mrbnf)) (vars @ passives) plives');
307315

308316
val fp_nesting_mrbnfs = nesting_mrbnfs lthy [map snd (#ctors spec)] (*(take (#rec_vars spec) (
309317
map_filter (fn (x, Live_Var) => SOME (TFree x) | _ => NONE) (#vars spec)
@@ -552,7 +560,7 @@ fun create_binder_datatype (spec : spec) lthy =
552560
in ((bset_opt, sets), Local_Defs.unfold0 lthy @{thms insert_is_Un[symmetric]} (Goal.prove_sorry lthy (names xs) [] goal (fn {context=ctxt, ...} => EVERY1 [
553561
K (Local_Defs.unfold0_tac ctxt (
554562
set_simp_thms @ map snd ctors @ #FVars_ctors quotient @ MRBNF_Def.set_defs_of_mrbnf pre_mrbnf
555-
@ [#Abs_inverse (snd info) OF @{thms UNIV_I}] @ #pset_ctors vvsubst_res
563+
@ [#Abs_inverse (snd info) OF @{thms UNIV_I}] @ the_default [] (Option.map (#pset_ctors o #vvsubst_res) vvsubst_res_opt)
556564
)),
557565
REPEAT_DETERM o EVERY' [
558566
EqSubst.eqsubst_tac ctxt [0] (maps MRBNF_Def.set_map_of_mrbnf fp_nesting_mrbnfs),
@@ -573,7 +581,7 @@ fun create_binder_datatype (spec : spec) lthy =
573581
]
574582
]))) end
575583
) ctors (#ctors spec))) end
576-
) (#FVarss quotient @ map fst (#psets vvsubst_res))));
584+
) (#FVarss quotient @ map fst (the_default [] (Option.map (#psets o #vvsubst_res) vvsubst_res_opt)))));
577585

578586
val ctors_tys = ctors ~~ map snd (#ctors spec);
579587
val distinct = flat (flat (map_index (fn (i, ((ctor, ctor_def), tys1)) => map_index (fn (j, ((ctor2, ctor2_def), tys2)) =>
@@ -596,12 +604,16 @@ fun create_binder_datatype (spec : spec) lthy =
596604

597605
val injects = @{map_filter 2} (fn ((ctor, ctor_def), tys) => fn setss => if null tys then NONE else
598606
let
607+
val class = if co then (* TODO *)
608+
[the (Var_Classes.get_class_for_bound (mk_card_suc (MRBNF_Def.bd_of_mrbnf mrbnf)) lthy)]
609+
else MRBNF_Def.class_of_mrbnf mrbnf;
610+
599611
val bound_tys = inter (op=) bounds (rev (map TFree (fold Term.add_tfreesT tys [])));
600612
val bfree_tys = inter (op=) bfrees (rev (map TFree (fold Term.add_tfreesT tys [])));
601613
val ((bound_tys', bfree_tys'), _) = lthy
602614
|> fold Variable.declare_typ (map fst replace @ map snd replace)
603-
|> mk_TFrees' (replicate (length bound_tys) (MRBNF_Def.class_of_mrbnf mrbnf))
604-
||>> mk_TFrees' (replicate (length bfree_tys) (MRBNF_Def.class_of_mrbnf mrbnf));
615+
|> mk_TFrees' (replicate (length bound_tys) class)
616+
||>> mk_TFrees' (replicate (length bfree_tys) class);
605617

606618
val tys' = map (Term.typ_subst_atomic replace) tys;
607619
val (((xs, ys), fs'), _) = names_lthy
@@ -610,7 +622,7 @@ fun create_binder_datatype (spec : spec) lthy =
610622
||>> mk_Frees "f" (map (fn a => a --> a) bound_tys');
611623

612624
val replace = map (fn (a, b) => if member (op=) bfrees a then
613-
(a, resort_tfree_or_tvar (MRBNF_Def.class_of_mrbnf mrbnf) (
625+
(a, resort_tfree_or_tvar class (
614626
Term.typ_subst_atomic (bound_tys ~~ bound_tys') (
615627
Term.typ_subst_atomic (map swap (filter (member (op=) bounds o fst) replace)) b
616628
)
@@ -788,7 +800,6 @@ fun create_binder_datatype (spec : spec) lthy =
788800
val goal = mk_Trueprop_eq (
789801
HOLogic.mk_eq (Term.list_comb (ctor, xs), Term.list_comb (ctor, ys)), rhs
790802
);
791-
val infinite_UNIV = @{thm cinfinite_imp_infinite} OF [MRBNF_Def.UNIV_cinfinite_of_mrbnf rec_mrbnf];
792803
in SOME (Goal.prove_sorry lthy (names (xs @ ys)) [] goal (fn {context=ctxt, ...} => EVERY1 [
793804
rtac ctxt trans,
794805
rtac ctxt inject,
@@ -808,7 +819,7 @@ fun create_binder_datatype (spec : spec) lthy =
808819
REPEAT_DETERM o EVERY' [
809820
TRY o rtac ctxt conjI,
810821
REPEAT_DETERM1 o FIRST' [
811-
resolve_tac ctxt (@{thms refl supp_id_bound bij_id bij_swap supp_swap_bound} @ [infinite_UNIV]),
822+
resolve_tac ctxt (@{thms refl supp_id_bound bij_id bij_swap supp_swap_bound infinite_class.infinite_UNIV}),
812823
assume_tac ctxt,
813824
resolve_tac ctxt (map map_cong0_of_mr_bnf (maps (map snd) mr_bnfs)),
814825
EVERY' [
@@ -827,7 +838,7 @@ fun create_binder_datatype (spec : spec) lthy =
827838
REPEAT_DETERM o rtac ctxt @{thm conjI[rotated]},
828839
REPEAT_DETERM o FIRST' [
829840
assume_tac ctxt,
830-
resolve_tac ctxt (@{thms swap_simps supp_swap_bound bij_swap} @ [infinite_UNIV]),
841+
resolve_tac ctxt (@{thms swap_simps supp_swap_bound bij_swap infinite_class.infinite_UNIV}),
831842
etac ctxt @{thm id_on_swap}
832843
]
833844
])) end
@@ -923,7 +934,7 @@ fun create_binder_datatype (spec : spec) lthy =
923934
| SOME t => SOME (f, map HOLogic.mk_Trueprop (if var_type = MRBNF_Def.Bound_Var then
924935
[mk_bij f, t] else [t]
925936
))
926-
) (take (length fs) (MRBNF_Def.var_types_of_mrbnf rec_mrbnf)) fs);
937+
) (take (length fs) (MRBNF_Def.var_types_of_mrbnf mrbnf)) fs);
927938

928939
fun mk_map (T as Type (n, Ts)) = (case MRBNF_Def.mrbnf_of lthy n of
929940
SOME mrbnf =>
@@ -1049,8 +1060,11 @@ fun create_binder_datatype (spec : spec) lthy =
10491060
) end
10501061
) ctors (#ctors spec) end;
10511062

1052-
val map_simps =
1063+
val map_simps = if co then [] else (* TODO *)
10531064
let
1065+
val rec_mrbnf = #rec_mrbnf (the vvsubst_res_opt)
1066+
val vvsubst_res = #vvsubst_res (the vvsubst_res_opt)
1067+
10541068
val (fs, _) = lthy
10551069
|> mk_Frees "f" (map2 (curry (op-->)) (vars @ passives) args');
10561070

@@ -1100,7 +1114,7 @@ fun create_binder_datatype (spec : spec) lthy =
11001114
])),
11011115
REPEAT_DETERM o resolve_tac ctxt prems,
11021116
REPEAT_DETERM o EVERY' [
1103-
EqSubst.eqsubst_tac ctxt [0] (map #map_permute nesting_binder_sugars),
1117+
EqSubst.eqsubst_tac ctxt [0] (map (the o #map_permute) nesting_binder_sugars),
11041118
REPEAT_DETERM o resolve_tac ctxt prems
11051119
],
11061120
K (Local_Defs.unfold0_tac ctxt @{thms id_apply}),
@@ -1117,8 +1131,9 @@ fun create_binder_datatype (spec : spec) lthy =
11171131
REPEAT_DETERM o resolve_tac ctxt (MRBNF_Def.UNIV_cinfinite_of_mrbnf mrbnf :: @{thms cmin_Cinfinite conjI card_of_Card_order})
11181132
]);
11191133

1120-
val (lthy, tvsubst_opt) = if not (null (map_filter I (#etas tvsubst_model))) then
1134+
val (lthy, tvsubst_opt) = if not (null (map_filter I (#etas tvsubst_model))) andalso not co then
11211135
let
1136+
val recursor_result = #recursor_result (the vvsubst_res_opt);
11221137
val (tvsubst_ress, lthy) = MRBNF_TVSubst.create_tvsubst_of_mrbnf (Binding.prefix_name "tv") res [tvsubst_model] (#QREC_cmin_fixed recursor_result) lthy;
11231138
val tvsubst_res = hd tvsubst_ress;
11241139
val tvsubst_simps =
@@ -1183,20 +1198,41 @@ fun create_binder_datatype (spec : spec) lthy =
11831198
val induct_attrib = Attrib.internal Position.none (K (Induct.induct_type (fst (dest_Type qT))))
11841199
val equiv = @{attributes [simp, equiv]}
11851200

1186-
val sugar = {
1187-
map_simps = map_simps,
1188-
set_simpss = set_simpss,
1189-
permute_simps = permute_simps,
1190-
map_permute = #vvsubst_permute vvsubst_res,
1191-
strong_induct = strong_induct_opt,
1192-
subst_simps = Option.map snd tvsubst_opt,
1193-
bsetss = bset_optss,
1194-
bset_bounds = [],
1195-
mrbnf = mrbnf,
1196-
distinct = distinct,
1197-
inject = injects,
1198-
ctors = ctors
1199-
} : binder_sugar;
1201+
val (sugar, lthy) = if co then
1202+
let
1203+
val (locale_name, lthy) = MRBNF_Corecursor.create_binding_corecursor I res lthy;
1204+
val sugar = {
1205+
map_simps = [],
1206+
set_simpss = [],
1207+
permute_simps = [],
1208+
map_permute = NONE,
1209+
strong_induct = NONE,
1210+
subst_simps = NONE,
1211+
bsetss = [],
1212+
bset_bounds = [],
1213+
mrbnf = mrbnf,
1214+
distinct = [],
1215+
inject = [],
1216+
ctors = []
1217+
} : binder_sugar;
1218+
in (sugar, lthy) end
1219+
else
1220+
let
1221+
val sugar = {
1222+
map_simps = map_simps,
1223+
set_simpss = set_simpss,
1224+
permute_simps = permute_simps,
1225+
map_permute = SOME (#vvsubst_permute (#vvsubst_res (the vvsubst_res_opt))),
1226+
strong_induct = strong_induct_opt,
1227+
subst_simps = Option.map snd tvsubst_opt,
1228+
bsetss = bset_optss,
1229+
bset_bounds = [],
1230+
mrbnf = mrbnf,
1231+
distinct = distinct,
1232+
inject = injects,
1233+
ctors = ctors
1234+
} : binder_sugar;
1235+
in (sugar, lthy) end
12001236

12011237
val lthy = register_binder_sugar (fst (dest_Type qT)) sugar lthy;
12021238

@@ -1213,11 +1249,12 @@ fun create_binder_datatype (spec : spec) lthy =
12131249
("distinct", distinct, simp),
12141250
("inject", injects, simp)
12151251
] @ the_default [] (Option.map (fn (_, tvsubst_simps) => [("subst", tvsubst_simps, simp)]) tvsubst_opt)
1216-
) |> (map (fn (thmN, thms, attrs) =>
1252+
)
1253+
|> filter_out (null o #2)
1254+
|> (map (fn (thmN, thms, attrs) =>
12171255
((Binding.qualify true (Binding.name_of (#fp_b spec)) (Binding.name thmN), attrs), [(thms, [])])
12181256
))
1219-
val (_, lthy) = Local_Theory.notes notes lthy
1220-
1257+
val (_, lthy) = Local_Theory.notes notes lthy;;
12211258
in (sugar, lthy) end;
12221259

12231260
end

0 commit comments

Comments
 (0)