src/HOL/Tools/BNF/Tools/bnf_lfp.ML
changeset 55058 4e700eb471d4
parent 54841 af71b753c459
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/HOL/Tools/BNF/Tools/bnf_lfp.ML	Mon Jan 20 18:24:56 2014 +0100
     1.3 @@ -0,0 +1,1881 @@
     1.4 +(*  Title:      HOL/BNF/Tools/bnf_lfp.ML
     1.5 +    Author:     Dmitriy Traytel, TU Muenchen
     1.6 +    Author:     Andrei Popescu, TU Muenchen
     1.7 +    Copyright   2012
     1.8 +
     1.9 +Datatype construction.
    1.10 +*)
    1.11 +
    1.12 +signature BNF_LFP =
    1.13 +sig
    1.14 +  val construct_lfp: mixfix list -> binding list -> binding list -> binding list list ->
    1.15 +    binding list -> (string * sort) list -> typ list * typ list list -> BNF_Def.bnf list ->
    1.16 +    local_theory -> BNF_FP_Util.fp_result * local_theory
    1.17 +end;
    1.18 +
    1.19 +structure BNF_LFP : BNF_LFP =
    1.20 +struct
    1.21 +
    1.22 +open BNF_Def
    1.23 +open BNF_Util
    1.24 +open BNF_Tactics
    1.25 +open BNF_Comp
    1.26 +open BNF_FP_Util
    1.27 +open BNF_FP_Def_Sugar
    1.28 +open BNF_LFP_Rec_Sugar
    1.29 +open BNF_LFP_Util
    1.30 +open BNF_LFP_Tactics
    1.31 +
    1.32 +(*all BNFs have the same lives*)
    1.33 +fun construct_lfp mixfixes map_bs rel_bs set_bss0 bs resBs (resDs, Dss) bnfs lthy =
    1.34 +  let
    1.35 +    val time = time lthy;
    1.36 +    val timer = time (Timer.startRealTimer ());
    1.37 +
    1.38 +    val live = live_of_bnf (hd bnfs);
    1.39 +    val n = length bnfs; (*active*)
    1.40 +    val ks = 1 upto n;
    1.41 +    val m = live - n; (*passive, if 0 don't generate a new BNF*)
    1.42 +
    1.43 +    val note_all = Config.get lthy bnf_note_all;
    1.44 +    val b_names = map Binding.name_of bs;
    1.45 +    val b_name = mk_common_name b_names;
    1.46 +    val b = Binding.name b_name;
    1.47 +    val mk_internal_b = Binding.name #> Binding.prefix true b_name #> Binding.conceal;
    1.48 +    fun mk_internal_bs name =
    1.49 +      map (fn b =>
    1.50 +        Binding.prefix true b_name (Binding.prefix_name (name ^ "_") b) |> Binding.conceal) bs;
    1.51 +    val external_bs = map2 (Binding.prefix false) b_names bs
    1.52 +      |> note_all = false ? map Binding.conceal;
    1.53 +
    1.54 +    (* TODO: check if m, n, etc., are sane *)
    1.55 +
    1.56 +    val deads = fold (union (op =)) Dss resDs;
    1.57 +    val names_lthy = fold Variable.declare_typ deads lthy;
    1.58 +    val passives = map fst (subtract (op = o apsnd TFree) deads resBs);
    1.59 +
    1.60 +    (* tvars *)
    1.61 +    val (((((passiveAs, activeAs), passiveBs), activeBs), passiveCs), activeCs) =
    1.62 +      names_lthy
    1.63 +      |> variant_tfrees passives
    1.64 +      ||>> mk_TFrees n
    1.65 +      ||>> variant_tfrees passives
    1.66 +      ||>> mk_TFrees n
    1.67 +      ||>> variant_tfrees passives
    1.68 +      ||>> mk_TFrees n
    1.69 +      |> fst;
    1.70 +
    1.71 +    val allAs = passiveAs @ activeAs;
    1.72 +    val allBs' = passiveBs @ activeBs;
    1.73 +    val Ass = replicate n allAs;
    1.74 +    val allBs = passiveAs @ activeBs;
    1.75 +    val Bss = replicate n allBs;
    1.76 +    val allCs = passiveAs @ activeCs;
    1.77 +    val allCs' = passiveBs @ activeCs;
    1.78 +    val Css' = replicate n allCs';
    1.79 +
    1.80 +    (* types *)
    1.81 +    val dead_poss =
    1.82 +      map (fn x => if member (op =) deads (TFree x) then SOME (TFree x) else NONE) resBs;
    1.83 +    fun mk_param NONE passive = (hd passive, tl passive)
    1.84 +      | mk_param (SOME a) passive = (a, passive);
    1.85 +    val mk_params = fold_map mk_param dead_poss #> fst;
    1.86 +
    1.87 +    fun mk_FTs Ts = map2 (fn Ds => mk_T_of_bnf Ds Ts) Dss bnfs;
    1.88 +    val (params, params') = `(map Term.dest_TFree) (mk_params passiveAs);
    1.89 +    val FTsAs = mk_FTs allAs;
    1.90 +    val FTsBs = mk_FTs allBs;
    1.91 +    val FTsCs = mk_FTs allCs;
    1.92 +    val ATs = map HOLogic.mk_setT passiveAs;
    1.93 +    val BTs = map HOLogic.mk_setT activeAs;
    1.94 +    val B'Ts = map HOLogic.mk_setT activeBs;
    1.95 +    val B''Ts = map HOLogic.mk_setT activeCs;
    1.96 +    val sTs = map2 (curry op -->) FTsAs activeAs;
    1.97 +    val s'Ts = map2 (curry op -->) FTsBs activeBs;
    1.98 +    val s''Ts = map2 (curry op -->) FTsCs activeCs;
    1.99 +    val fTs = map2 (curry op -->) activeAs activeBs;
   1.100 +    val inv_fTs = map2 (curry op -->) activeBs activeAs;
   1.101 +    val self_fTs = map2 (curry op -->) activeAs activeAs;
   1.102 +    val gTs = map2 (curry op -->) activeBs activeCs;
   1.103 +    val all_gTs = map2 (curry op -->) allBs allCs';
   1.104 +    val prodBsAs = map2 (curry HOLogic.mk_prodT) activeBs activeAs;
   1.105 +    val prodFTs = mk_FTs (passiveAs @ prodBsAs);
   1.106 +    val prod_sTs = map2 (curry op -->) prodFTs activeAs;
   1.107 +
   1.108 +    (* terms *)
   1.109 +    val mapsAsAs = map4 mk_map_of_bnf Dss Ass Ass bnfs;
   1.110 +    val mapsAsBs = map4 mk_map_of_bnf Dss Ass Bss bnfs;
   1.111 +    val mapsBsAs = map4 mk_map_of_bnf Dss Bss Ass bnfs;
   1.112 +    val mapsBsCs' = map4 mk_map_of_bnf Dss Bss Css' bnfs;
   1.113 +    val mapsAsCs' = map4 mk_map_of_bnf Dss Ass Css' bnfs;
   1.114 +    val map_fsts = map4 mk_map_of_bnf Dss (replicate n (passiveAs @ prodBsAs)) Bss bnfs;
   1.115 +    val map_fsts_rev = map4 mk_map_of_bnf Dss Bss (replicate n (passiveAs @ prodBsAs)) bnfs;
   1.116 +    fun mk_setss Ts = map3 mk_sets_of_bnf (map (replicate live) Dss)
   1.117 +      (map (replicate live) (replicate n Ts)) bnfs;
   1.118 +    val setssAs = mk_setss allAs;
   1.119 +    val bd0s = map3 mk_bd_of_bnf Dss Ass bnfs;
   1.120 +    val bds =
   1.121 +      map3 (fn bd0 => fn Ds => fn bnf => mk_csum bd0
   1.122 +        (mk_card_of (HOLogic.mk_UNIV
   1.123 +          (mk_T_of_bnf Ds (replicate live (fst (dest_relT (fastype_of bd0)))) bnf))))
   1.124 +      bd0s Dss bnfs;
   1.125 +    val witss = map wits_of_bnf bnfs;
   1.126 +
   1.127 +    val (((((((((((((((((((zs, zs'), As), Bs), Bs_copy), B's), B''s), ss), prod_ss), s's), s''s),
   1.128 +      fs), fs_copy), inv_fs), self_fs), gs), all_gs), (xFs, xFs')), (yFs, yFs')),
   1.129 +      names_lthy) = lthy
   1.130 +      |> mk_Frees' "z" activeAs
   1.131 +      ||>> mk_Frees "A" ATs
   1.132 +      ||>> mk_Frees "B" BTs
   1.133 +      ||>> mk_Frees "B" BTs
   1.134 +      ||>> mk_Frees "B'" B'Ts
   1.135 +      ||>> mk_Frees "B''" B''Ts
   1.136 +      ||>> mk_Frees "s" sTs
   1.137 +      ||>> mk_Frees "prods" prod_sTs
   1.138 +      ||>> mk_Frees "s'" s'Ts
   1.139 +      ||>> mk_Frees "s''" s''Ts
   1.140 +      ||>> mk_Frees "f" fTs
   1.141 +      ||>> mk_Frees "f" fTs
   1.142 +      ||>> mk_Frees "f" inv_fTs
   1.143 +      ||>> mk_Frees "f" self_fTs
   1.144 +      ||>> mk_Frees "g" gTs
   1.145 +      ||>> mk_Frees "g" all_gTs
   1.146 +      ||>> mk_Frees' "x" FTsAs
   1.147 +      ||>> mk_Frees' "y" FTsBs;
   1.148 +
   1.149 +    val passive_UNIVs = map HOLogic.mk_UNIV passiveAs;
   1.150 +    val active_UNIVs = map HOLogic.mk_UNIV activeAs;
   1.151 +    val prod_UNIVs = map HOLogic.mk_UNIV prodBsAs;
   1.152 +    val passive_ids = map HOLogic.id_const passiveAs;
   1.153 +    val active_ids = map HOLogic.id_const activeAs;
   1.154 +    val fsts = map fst_const prodBsAs;
   1.155 +
   1.156 +    (* thms *)
   1.157 +    val bd0_card_orders = map bd_card_order_of_bnf bnfs;
   1.158 +    val bd0_Card_orders = map bd_Card_order_of_bnf bnfs;
   1.159 +    val bd0_Cinfinites = map bd_Cinfinite_of_bnf bnfs;
   1.160 +    val set_bd0ss = map set_bd_of_bnf bnfs;
   1.161 +
   1.162 +    val bd_card_orders =
   1.163 +      map (fn thm => @{thm card_order_csum} OF [thm, @{thm card_of_card_order_on}]) bd0_card_orders;
   1.164 +    val bd_Card_order = @{thm Card_order_csum};
   1.165 +    val bd_Card_orders = replicate n bd_Card_order;
   1.166 +    val bd_Cinfinites = map (fn thm => thm RS @{thm Cinfinite_csum1}) bd0_Cinfinites;
   1.167 +    val bd_Cnotzeros = map (fn thm => thm RS @{thm Cinfinite_Cnotzero}) bd_Cinfinites;
   1.168 +    val bd_Cinfinite = hd bd_Cinfinites;
   1.169 +    val bd_Cnotzero = hd bd_Cnotzeros;
   1.170 +    val set_bdss =
   1.171 +      map2 (fn set_bd0s => fn bd0_Card_order =>
   1.172 +        map (fn thm => ctrans OF [thm, bd0_Card_order RS @{thm ordLeq_csum1}]) set_bd0s)
   1.173 +      set_bd0ss bd0_Card_orders;
   1.174 +    val in_bds = map in_bd_of_bnf bnfs;
   1.175 +    val sym_map_comps = map (fn bnf => map_comp0_of_bnf bnf RS sym) bnfs;
   1.176 +    val map_comps = map map_comp_of_bnf bnfs;
   1.177 +    val map_cong0s = map map_cong0_of_bnf bnfs;
   1.178 +    val map_id0s = map map_id0_of_bnf bnfs;
   1.179 +    val map_ids = map map_id_of_bnf bnfs;
   1.180 +    val set_mapss = map set_map_of_bnf bnfs;
   1.181 +    val rel_mono_strongs = map rel_mono_strong_of_bnf bnfs;
   1.182 +    val rel_OOs = map rel_OO_of_bnf bnfs;
   1.183 +
   1.184 +    val timer = time (timer "Extracted terms & thms");
   1.185 +
   1.186 +    (* nonemptiness check *)
   1.187 +    fun new_wit X (wit: nonemptiness_witness) = subset (op =) (#I wit, (0 upto m - 1) @ map snd X);
   1.188 +
   1.189 +    val all = m upto m + n - 1;
   1.190 +
   1.191 +    fun enrich X = map_filter (fn i =>
   1.192 +      (case find_first (fn (_, i') => i = i') X of
   1.193 +        NONE =>
   1.194 +          (case find_index (new_wit X) (nth witss (i - m)) of
   1.195 +            ~1 => NONE
   1.196 +          | j => SOME (j, i))
   1.197 +      | SOME ji => SOME ji)) all;
   1.198 +    val reachable = fixpoint (op =) enrich [];
   1.199 +    val _ = (case subtract (op =) (map snd reachable) all of
   1.200 +        [] => ()
   1.201 +      | i :: _ => error ("Cannot define empty datatype " ^ quote (Binding.name_of (nth bs (i - m)))));
   1.202 +
   1.203 +    val wit_thms = flat (map2 (fn bnf => fn (j, _) => nth (wit_thmss_of_bnf bnf) j) bnfs reachable);
   1.204 +
   1.205 +    val timer = time (timer "Checked nonemptiness");
   1.206 +
   1.207 +    (* derived thms *)
   1.208 +
   1.209 +    (*map g1 ... gm g(m+1) ... g(m+n) (map id ... id f(m+1) ... f(m+n) x) =
   1.210 +      map g1 ... gm (g(m+1) o f(m+1)) ... (g(m+n) o f(m+n)) x*)
   1.211 +    fun mk_map_comp_id x mapAsBs mapBsCs mapAsCs map_comp0 =
   1.212 +      let
   1.213 +        val lhs = Term.list_comb (mapBsCs, all_gs) $
   1.214 +          (Term.list_comb (mapAsBs, passive_ids @ fs) $ x);
   1.215 +        val rhs = Term.list_comb (mapAsCs,
   1.216 +          take m all_gs @ map HOLogic.mk_comp (drop m all_gs ~~ fs)) $ x;
   1.217 +      in
   1.218 +        Goal.prove_sorry lthy [] []
   1.219 +          (fold_rev Logic.all (x :: fs @ all_gs) (mk_Trueprop_eq (lhs, rhs)))
   1.220 +          (K (mk_map_comp_id_tac map_comp0))
   1.221 +        |> Thm.close_derivation
   1.222 +      end;
   1.223 +
   1.224 +    val map_comp_id_thms = map5 mk_map_comp_id xFs mapsAsBs mapsBsCs' mapsAsCs' map_comps;
   1.225 +
   1.226 +    (*forall a : set(m+1) x. f(m+1) a = a; ...; forall a : set(m+n) x. f(m+n) a = a ==>
   1.227 +      map id ... id f(m+1) ... f(m+n) x = x*)
   1.228 +    fun mk_map_cong0L x mapAsAs sets map_cong0 map_id =
   1.229 +      let
   1.230 +        fun mk_prem set f z z' = HOLogic.mk_Trueprop
   1.231 +          (mk_Ball (set $ x) (Term.absfree z' (HOLogic.mk_eq (f $ z, z))));
   1.232 +        val prems = map4 mk_prem (drop m sets) self_fs zs zs';
   1.233 +        val goal = mk_Trueprop_eq (Term.list_comb (mapAsAs, passive_ids @ self_fs) $ x, x);
   1.234 +      in
   1.235 +        Goal.prove_sorry lthy [] []
   1.236 +          (fold_rev Logic.all (x :: self_fs) (Logic.list_implies (prems, goal)))
   1.237 +          (K (mk_map_cong0L_tac m map_cong0 map_id))
   1.238 +        |> Thm.close_derivation
   1.239 +      end;
   1.240 +
   1.241 +    val map_cong0L_thms = map5 mk_map_cong0L xFs mapsAsAs setssAs map_cong0s map_ids;
   1.242 +    val in_mono'_thms = map (fn bnf => in_mono_of_bnf bnf OF (replicate m subset_refl)) bnfs;
   1.243 +    val in_cong'_thms = map (fn bnf => in_cong_of_bnf bnf OF (replicate m refl)) bnfs;
   1.244 +
   1.245 +    val timer = time (timer "Derived simple theorems");
   1.246 +
   1.247 +    (* algebra *)
   1.248 +
   1.249 +    val alg_bind = mk_internal_b algN;
   1.250 +    val alg_name = Binding.name_of alg_bind;
   1.251 +    val alg_def_bind = (Thm.def_binding alg_bind, []);
   1.252 +
   1.253 +    (*forall i = 1 ... n: (\<forall>x \<in> Fi_in A1 .. Am B1 ... Bn. si x \<in> Bi)*)
   1.254 +    val alg_spec =
   1.255 +      let
   1.256 +        val algT = Library.foldr (op -->) (ATs @ BTs @ sTs, HOLogic.boolT);
   1.257 +
   1.258 +        val ins = map3 mk_in (replicate n (As @ Bs)) setssAs FTsAs;
   1.259 +        fun mk_alg_conjunct B s X x x' =
   1.260 +          mk_Ball X (Term.absfree x' (HOLogic.mk_mem (s $ x, B)));
   1.261 +
   1.262 +        val lhs = Term.list_comb (Free (alg_name, algT), As @ Bs @ ss);
   1.263 +        val rhs = Library.foldr1 HOLogic.mk_conj (map5 mk_alg_conjunct Bs ss ins xFs xFs')
   1.264 +      in
   1.265 +        mk_Trueprop_eq (lhs, rhs)
   1.266 +      end;
   1.267 +
   1.268 +    val ((alg_free, (_, alg_def_free)), (lthy, lthy_old)) =
   1.269 +        lthy
   1.270 +        |> Specification.definition (SOME (alg_bind, NONE, NoSyn), (alg_def_bind, alg_spec))
   1.271 +        ||> `Local_Theory.restore;
   1.272 +
   1.273 +    val phi = Proof_Context.export_morphism lthy_old lthy;
   1.274 +    val alg = fst (Term.dest_Const (Morphism.term phi alg_free));
   1.275 +    val alg_def = Morphism.thm phi alg_def_free;
   1.276 +
   1.277 +    fun mk_alg As Bs ss =
   1.278 +      let
   1.279 +        val args = As @ Bs @ ss;
   1.280 +        val Ts = map fastype_of args;
   1.281 +        val algT = Library.foldr (op -->) (Ts, HOLogic.boolT);
   1.282 +      in
   1.283 +        Term.list_comb (Const (alg, algT), args)
   1.284 +      end;
   1.285 +
   1.286 +    val alg_set_thms =
   1.287 +      let
   1.288 +        val alg_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   1.289 +        fun mk_prem x set B = HOLogic.mk_Trueprop (mk_leq (set $ x) B);
   1.290 +        fun mk_concl s x B = HOLogic.mk_Trueprop (HOLogic.mk_mem (s $ x, B));
   1.291 +        val premss = map2 ((fn x => fn sets =>  map2 (mk_prem x) sets (As @ Bs))) xFs setssAs;
   1.292 +        val concls = map3 mk_concl ss xFs Bs;
   1.293 +        val goals = map3 (fn x => fn prems => fn concl =>
   1.294 +          fold_rev Logic.all (x :: As @ Bs @ ss)
   1.295 +            (Logic.list_implies (alg_prem :: prems, concl))) xFs premss concls;
   1.296 +      in
   1.297 +        map (fn goal =>
   1.298 +          Goal.prove_sorry lthy [] [] goal (K (mk_alg_set_tac alg_def)) |> Thm.close_derivation)
   1.299 +        goals
   1.300 +      end;
   1.301 +
   1.302 +    fun mk_talg ATs BTs = mk_alg (map HOLogic.mk_UNIV ATs) (map HOLogic.mk_UNIV BTs);
   1.303 +
   1.304 +    val talg_thm =
   1.305 +      let
   1.306 +        val goal = fold_rev Logic.all ss
   1.307 +          (HOLogic.mk_Trueprop (mk_talg passiveAs activeAs ss))
   1.308 +      in
   1.309 +        Goal.prove_sorry lthy [] [] goal
   1.310 +          (K (stac alg_def 1 THEN CONJ_WRAP (K (EVERY' [rtac ballI, rtac UNIV_I] 1)) ss))
   1.311 +        |> Thm.close_derivation
   1.312 +      end;
   1.313 +
   1.314 +    val timer = time (timer "Algebra definition & thms");
   1.315 +
   1.316 +    val alg_not_empty_thms =
   1.317 +      let
   1.318 +        val alg_prem =
   1.319 +          HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   1.320 +        val concls = map (HOLogic.mk_Trueprop o mk_not_empty) Bs;
   1.321 +        val goals =
   1.322 +          map (fn concl =>
   1.323 +            fold_rev Logic.all (Bs @ ss) (Logic.mk_implies (alg_prem, concl))) concls;
   1.324 +      in
   1.325 +        map2 (fn goal => fn alg_set =>
   1.326 +          Goal.prove_sorry lthy [] []
   1.327 +            goal (K (mk_alg_not_empty_tac lthy alg_set alg_set_thms wit_thms))
   1.328 +          |> Thm.close_derivation)
   1.329 +        goals alg_set_thms
   1.330 +      end;
   1.331 +
   1.332 +    val timer = time (timer "Proved nonemptiness");
   1.333 +
   1.334 +    (* morphism *)
   1.335 +
   1.336 +    val mor_bind = mk_internal_b morN;
   1.337 +    val mor_name = Binding.name_of mor_bind;
   1.338 +    val mor_def_bind = (Thm.def_binding mor_bind, []);
   1.339 +
   1.340 +    (*fbetw) forall i = 1 ... n: (\<forall>x \<in> Bi. f x \<in> B'i)*)
   1.341 +    (*mor) forall i = 1 ... n: (\<forall>x \<in> Fi_in UNIV ... UNIV B1 ... Bn.
   1.342 +       f (s1 x) = s1' (Fi_map id ... id f1 ... fn x))*)
   1.343 +    val mor_spec =
   1.344 +      let
   1.345 +        val morT = Library.foldr (op -->) (BTs @ sTs @ B'Ts @ s'Ts @ fTs, HOLogic.boolT);
   1.346 +
   1.347 +        fun mk_fbetw f B1 B2 z z' =
   1.348 +          mk_Ball B1 (Term.absfree z' (HOLogic.mk_mem (f $ z, B2)));
   1.349 +        fun mk_mor sets mapAsBs f s s' T x x' =
   1.350 +          mk_Ball (mk_in (passive_UNIVs @ Bs) sets T)
   1.351 +            (Term.absfree x' (HOLogic.mk_eq (f $ (s $ x), s' $
   1.352 +              (Term.list_comb (mapAsBs, passive_ids @ fs) $ x))));
   1.353 +        val lhs = Term.list_comb (Free (mor_name, morT), Bs @ ss @ B's @ s's @ fs);
   1.354 +        val rhs = HOLogic.mk_conj
   1.355 +          (Library.foldr1 HOLogic.mk_conj (map5 mk_fbetw fs Bs B's zs zs'),
   1.356 +          Library.foldr1 HOLogic.mk_conj
   1.357 +            (map8 mk_mor setssAs mapsAsBs fs ss s's FTsAs xFs xFs'))
   1.358 +      in
   1.359 +        mk_Trueprop_eq (lhs, rhs)
   1.360 +      end;
   1.361 +
   1.362 +    val ((mor_free, (_, mor_def_free)), (lthy, lthy_old)) =
   1.363 +        lthy
   1.364 +        |> Specification.definition (SOME (mor_bind, NONE, NoSyn), (mor_def_bind, mor_spec))
   1.365 +        ||> `Local_Theory.restore;
   1.366 +
   1.367 +    val phi = Proof_Context.export_morphism lthy_old lthy;
   1.368 +    val mor = fst (Term.dest_Const (Morphism.term phi mor_free));
   1.369 +    val mor_def = Morphism.thm phi mor_def_free;
   1.370 +
   1.371 +    fun mk_mor Bs1 ss1 Bs2 ss2 fs =
   1.372 +      let
   1.373 +        val args = Bs1 @ ss1 @ Bs2 @ ss2 @ fs;
   1.374 +        val Ts = map fastype_of (Bs1 @ ss1 @ Bs2 @ ss2 @ fs);
   1.375 +        val morT = Library.foldr (op -->) (Ts, HOLogic.boolT);
   1.376 +      in
   1.377 +        Term.list_comb (Const (mor, morT), args)
   1.378 +      end;
   1.379 +
   1.380 +    val (mor_image_thms, morE_thms) =
   1.381 +      let
   1.382 +        val prem = HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs);
   1.383 +        fun mk_image_goal f B1 B2 = fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs)
   1.384 +          (Logic.mk_implies (prem, HOLogic.mk_Trueprop (mk_leq (mk_image f $ B1) B2)));
   1.385 +        val image_goals = map3 mk_image_goal fs Bs B's;
   1.386 +        fun mk_elim_prem sets x T = HOLogic.mk_Trueprop
   1.387 +          (HOLogic.mk_mem (x, mk_in (passive_UNIVs @ Bs) sets T));
   1.388 +        fun mk_elim_goal sets mapAsBs f s s' x T =
   1.389 +          fold_rev Logic.all (x :: Bs @ ss @ B's @ s's @ fs)
   1.390 +            (Logic.list_implies ([prem, mk_elim_prem sets x T],
   1.391 +              mk_Trueprop_eq (f $ (s $ x), s' $ Term.list_comb (mapAsBs, passive_ids @ fs @ [x]))));
   1.392 +        val elim_goals = map7 mk_elim_goal setssAs mapsAsBs fs ss s's xFs FTsAs;
   1.393 +        fun prove goal =
   1.394 +          Goal.prove_sorry lthy [] [] goal (K (mk_mor_elim_tac mor_def)) |> Thm.close_derivation;
   1.395 +      in
   1.396 +        (map prove image_goals, map prove elim_goals)
   1.397 +      end;
   1.398 +
   1.399 +    val mor_incl_thm =
   1.400 +      let
   1.401 +        val prems = map2 (HOLogic.mk_Trueprop oo mk_leq) Bs Bs_copy;
   1.402 +        val concl = HOLogic.mk_Trueprop (mk_mor Bs ss Bs_copy ss active_ids);
   1.403 +      in
   1.404 +        Goal.prove_sorry lthy [] []
   1.405 +          (fold_rev Logic.all (Bs @ ss @ Bs_copy) (Logic.list_implies (prems, concl)))
   1.406 +          (K (mk_mor_incl_tac mor_def map_ids))
   1.407 +        |> Thm.close_derivation
   1.408 +      end;
   1.409 +
   1.410 +    val mor_comp_thm =
   1.411 +      let
   1.412 +        val prems =
   1.413 +          [HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs),
   1.414 +           HOLogic.mk_Trueprop (mk_mor B's s's B''s s''s gs)];
   1.415 +        val concl =
   1.416 +          HOLogic.mk_Trueprop (mk_mor Bs ss B''s s''s (map2 (curry HOLogic.mk_comp) gs fs));
   1.417 +      in
   1.418 +        Goal.prove_sorry lthy [] []
   1.419 +          (fold_rev Logic.all (Bs @ ss @ B's @ s's @ B''s @ s''s @ fs @ gs)
   1.420 +             (Logic.list_implies (prems, concl)))
   1.421 +          (K (mk_mor_comp_tac mor_def set_mapss map_comp_id_thms))
   1.422 +        |> Thm.close_derivation
   1.423 +      end;
   1.424 +
   1.425 +    val mor_inv_thm =
   1.426 +      let
   1.427 +        fun mk_inv_prem f inv_f B B' = HOLogic.mk_conj (mk_leq (mk_image inv_f $ B') B,
   1.428 +          HOLogic.mk_conj (mk_inver inv_f f B, mk_inver f inv_f B'));
   1.429 +        val prems = map HOLogic.mk_Trueprop
   1.430 +          ([mk_mor Bs ss B's s's fs,
   1.431 +          mk_alg passive_UNIVs Bs ss,
   1.432 +          mk_alg passive_UNIVs B's s's] @
   1.433 +          map4 mk_inv_prem fs inv_fs Bs B's);
   1.434 +        val concl = HOLogic.mk_Trueprop (mk_mor B's s's Bs ss inv_fs);
   1.435 +      in
   1.436 +        Goal.prove_sorry lthy [] []
   1.437 +          (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs @ inv_fs)
   1.438 +            (Logic.list_implies (prems, concl)))
   1.439 +          (K (mk_mor_inv_tac alg_def mor_def set_mapss morE_thms map_comp_id_thms map_cong0L_thms))
   1.440 +        |> Thm.close_derivation
   1.441 +      end;
   1.442 +
   1.443 +    val mor_cong_thm =
   1.444 +      let
   1.445 +        val prems = map HOLogic.mk_Trueprop
   1.446 +         (map2 (curry HOLogic.mk_eq) fs_copy fs @ [mk_mor Bs ss B's s's fs])
   1.447 +        val concl = HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs_copy);
   1.448 +      in
   1.449 +        Goal.prove_sorry lthy [] []
   1.450 +          (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs @ fs_copy)
   1.451 +             (Logic.list_implies (prems, concl)))
   1.452 +          (K ((hyp_subst_tac lthy THEN' atac) 1))
   1.453 +        |> Thm.close_derivation
   1.454 +      end;
   1.455 +
   1.456 +    val mor_str_thm =
   1.457 +      let
   1.458 +        val maps = map2 (fn Ds => fn bnf => Term.list_comb
   1.459 +          (mk_map_of_bnf Ds (passiveAs @ FTsAs) allAs bnf, passive_ids @ ss)) Dss bnfs;
   1.460 +      in
   1.461 +        Goal.prove_sorry lthy [] []
   1.462 +          (fold_rev Logic.all ss (HOLogic.mk_Trueprop
   1.463 +            (mk_mor (map HOLogic.mk_UNIV FTsAs) maps active_UNIVs ss ss)))
   1.464 +          (K (mk_mor_str_tac ks mor_def))
   1.465 +        |> Thm.close_derivation
   1.466 +      end;
   1.467 +
   1.468 +    val mor_convol_thm =
   1.469 +      let
   1.470 +        val maps = map3 (fn s => fn prod_s => fn mapx =>
   1.471 +          mk_convol (HOLogic.mk_comp (s, Term.list_comb (mapx, passive_ids @ fsts)), prod_s))
   1.472 +          s's prod_ss map_fsts;
   1.473 +      in
   1.474 +        Goal.prove_sorry lthy [] []
   1.475 +          (fold_rev Logic.all (s's @ prod_ss) (HOLogic.mk_Trueprop
   1.476 +            (mk_mor prod_UNIVs maps (map HOLogic.mk_UNIV activeBs) s's fsts)))
   1.477 +          (K (mk_mor_convol_tac ks mor_def))
   1.478 +        |> Thm.close_derivation
   1.479 +      end;
   1.480 +
   1.481 +    val mor_UNIV_thm =
   1.482 +      let
   1.483 +        fun mk_conjunct mapAsBs f s s' = HOLogic.mk_eq
   1.484 +            (HOLogic.mk_comp (f, s),
   1.485 +            HOLogic.mk_comp (s', Term.list_comb (mapAsBs, passive_ids @ fs)));
   1.486 +        val lhs = mk_mor active_UNIVs ss (map HOLogic.mk_UNIV activeBs) s's fs;
   1.487 +        val rhs = Library.foldr1 HOLogic.mk_conj (map4 mk_conjunct mapsAsBs fs ss s's);
   1.488 +      in
   1.489 +        Goal.prove_sorry lthy [] [] (fold_rev Logic.all (ss @ s's @ fs) (mk_Trueprop_eq (lhs, rhs)))
   1.490 +          (K (mk_mor_UNIV_tac m morE_thms mor_def))
   1.491 +        |> Thm.close_derivation
   1.492 +      end;
   1.493 +
   1.494 +    val timer = time (timer "Morphism definition & thms");
   1.495 +
   1.496 +    (* isomorphism *)
   1.497 +
   1.498 +    (*mor Bs1 ss1 Bs2 ss2 fs \<and> (\<exists>gs. mor Bs2 ss2 Bs1 ss1 fs \<and>
   1.499 +       forall i = 1 ... n. (inver gs[i] fs[i] Bs1[i] \<and> inver fs[i] gs[i] Bs2[i]))*)
   1.500 +    fun mk_iso Bs1 ss1 Bs2 ss2 fs gs =
   1.501 +      let
   1.502 +        val ex_inv_mor = list_exists_free gs
   1.503 +          (HOLogic.mk_conj (mk_mor Bs2 ss2 Bs1 ss1 gs,
   1.504 +            Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_conj)
   1.505 +              (map3 mk_inver gs fs Bs1) (map3 mk_inver fs gs Bs2))));
   1.506 +      in
   1.507 +        HOLogic.mk_conj (mk_mor Bs1 ss1 Bs2 ss2 fs, ex_inv_mor)
   1.508 +      end;
   1.509 +
   1.510 +    val iso_alt_thm =
   1.511 +      let
   1.512 +        val prems = map HOLogic.mk_Trueprop
   1.513 +         [mk_alg passive_UNIVs Bs ss,
   1.514 +         mk_alg passive_UNIVs B's s's]
   1.515 +        val concl = mk_Trueprop_eq (mk_iso Bs ss B's s's fs inv_fs,
   1.516 +          HOLogic.mk_conj (mk_mor Bs ss B's s's fs,
   1.517 +            Library.foldr1 HOLogic.mk_conj (map3 mk_bij_betw fs Bs B's)));
   1.518 +      in
   1.519 +        Goal.prove_sorry lthy [] []
   1.520 +          (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs) (Logic.list_implies (prems, concl)))
   1.521 +          (K (mk_iso_alt_tac mor_image_thms mor_inv_thm))
   1.522 +        |> Thm.close_derivation
   1.523 +      end;
   1.524 +
   1.525 +    val timer = time (timer "Isomorphism definition & thms");
   1.526 +
   1.527 +    (* algebra copies *)
   1.528 +
   1.529 +    val (copy_alg_thm, ex_copy_alg_thm) =
   1.530 +      let
   1.531 +        val prems = map HOLogic.mk_Trueprop
   1.532 +         (mk_alg passive_UNIVs Bs ss :: map3 mk_bij_betw inv_fs B's Bs);
   1.533 +        val inver_prems = map HOLogic.mk_Trueprop
   1.534 +          (map3 mk_inver inv_fs fs Bs @ map3 mk_inver fs inv_fs B's);
   1.535 +        val all_prems = prems @ inver_prems;
   1.536 +        fun mk_s f s mapT y y' = Term.absfree y' (f $ (s $
   1.537 +          (Term.list_comb (mapT, passive_ids @ inv_fs) $ y)));
   1.538 +
   1.539 +        val alg = HOLogic.mk_Trueprop
   1.540 +          (mk_alg passive_UNIVs B's (map5 mk_s fs ss mapsBsAs yFs yFs'));
   1.541 +        val copy_str_thm = Goal.prove_sorry lthy [] []
   1.542 +          (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   1.543 +            (Logic.list_implies (all_prems, alg)))
   1.544 +          (K (mk_copy_str_tac set_mapss alg_def alg_set_thms))
   1.545 +          |> Thm.close_derivation;
   1.546 +
   1.547 +        val iso = HOLogic.mk_Trueprop
   1.548 +          (mk_iso B's (map5 mk_s fs ss mapsBsAs yFs yFs') Bs ss inv_fs fs_copy);
   1.549 +        val copy_alg_thm = Goal.prove_sorry lthy [] []
   1.550 +          (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   1.551 +            (Logic.list_implies (all_prems, iso)))
   1.552 +          (K (mk_copy_alg_tac set_mapss alg_set_thms mor_def iso_alt_thm copy_str_thm))
   1.553 +          |> Thm.close_derivation;
   1.554 +
   1.555 +        val ex = HOLogic.mk_Trueprop
   1.556 +          (list_exists_free s's
   1.557 +            (HOLogic.mk_conj (mk_alg passive_UNIVs B's s's,
   1.558 +              mk_iso B's s's Bs ss inv_fs fs_copy)));
   1.559 +        val ex_copy_alg_thm = Goal.prove_sorry lthy [] []
   1.560 +          (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   1.561 +             (Logic.list_implies (prems, ex)))
   1.562 +          (K (mk_ex_copy_alg_tac n copy_str_thm copy_alg_thm))
   1.563 +          |> Thm.close_derivation;
   1.564 +      in
   1.565 +        (copy_alg_thm, ex_copy_alg_thm)
   1.566 +      end;
   1.567 +
   1.568 +    val timer = time (timer "Copy thms");
   1.569 +
   1.570 +
   1.571 +    (* bounds *)
   1.572 +
   1.573 +    val sum_Card_order = if n = 1 then bd_Card_order else @{thm Card_order_csum};
   1.574 +    val sum_Cnotzero = if n = 1 then bd_Cnotzero else bd_Cnotzero RS @{thm csum_Cnotzero1};
   1.575 +    val sum_Cinfinite = if n = 1 then bd_Cinfinite else bd_Cinfinite RS @{thm Cinfinite_csum1};
   1.576 +    fun mk_set_bd_sums i bd_Card_order bds =
   1.577 +      if n = 1 then bds
   1.578 +      else map (fn thm => bd_Card_order RS mk_ordLeq_csum n i thm) bds;
   1.579 +    val set_bd_sumss = map3 mk_set_bd_sums ks bd_Card_orders set_bdss;
   1.580 +
   1.581 +    fun mk_in_bd_sum i Co Cnz bd =
   1.582 +      if n = 1 then bd
   1.583 +      else Cnz RS ((Co RS mk_ordLeq_csum n i (Co RS @{thm ordLeq_refl})) RS
   1.584 +        (bd RS @{thm ordLeq_transitive[OF _ cexp_mono2_Cnotzero[OF _ Card_order_csum]]}));
   1.585 +    val in_bd_sums = map4 mk_in_bd_sum ks bd_Card_orders bd_Cnotzeros in_bds;
   1.586 +
   1.587 +    val sum_bd = Library.foldr1 (uncurry mk_csum) bds;
   1.588 +    val suc_bd = mk_cardSuc sum_bd;
   1.589 +    val field_suc_bd = mk_Field suc_bd;
   1.590 +    val suc_bdT = fst (dest_relT (fastype_of suc_bd));
   1.591 +    fun mk_Asuc_bd [] = mk_cexp ctwo suc_bd
   1.592 +      | mk_Asuc_bd As =
   1.593 +        mk_cexp (mk_csum (Library.foldr1 (uncurry mk_csum) (map mk_card_of As)) ctwo) suc_bd;
   1.594 +
   1.595 +    val suc_bd_Card_order = if n = 1 then bd_Card_order RS @{thm cardSuc_Card_order}
   1.596 +      else @{thm cardSuc_Card_order[OF Card_order_csum]};
   1.597 +    val suc_bd_Cinfinite = if n = 1 then bd_Cinfinite RS @{thm Cinfinite_cardSuc}
   1.598 +      else bd_Cinfinite RS @{thm Cinfinite_cardSuc[OF Cinfinite_csum1]};
   1.599 +    val suc_bd_Cnotzero = suc_bd_Cinfinite RS @{thm Cinfinite_Cnotzero};
   1.600 +    val suc_bd_worel = suc_bd_Card_order RS @{thm Card_order_wo_rel}
   1.601 +    val basis_Asuc = if m = 0 then @{thm ordLeq_refl[OF Card_order_ctwo]}
   1.602 +        else @{thm ordLeq_csum2[OF Card_order_ctwo]};
   1.603 +    val Asuc_bd_Cinfinite = suc_bd_Cinfinite RS (basis_Asuc RS @{thm Cinfinite_cexp});
   1.604 +
   1.605 +    val suc_bd_Asuc_bd = @{thm ordLess_ordLeq_trans[OF ordLess_ctwo_cexp cexp_mono1]} OF
   1.606 +      [suc_bd_Card_order, basis_Asuc, suc_bd_Card_order];
   1.607 +
   1.608 +    val Asuc_bdT = fst (dest_relT (fastype_of (mk_Asuc_bd As)));
   1.609 +    val II_BTs = replicate n (HOLogic.mk_setT Asuc_bdT);
   1.610 +    val II_sTs = map2 (fn Ds => fn bnf =>
   1.611 +      mk_T_of_bnf Ds (passiveAs @ replicate n Asuc_bdT) bnf --> Asuc_bdT) Dss bnfs;
   1.612 +
   1.613 +    val (((((((idxs, Asi_name), (idx, idx')), (jdx, jdx')), II_Bs), II_ss), Asuc_fs),
   1.614 +      names_lthy) = names_lthy
   1.615 +      |> mk_Frees "i" (replicate n suc_bdT)
   1.616 +      ||>> (fn ctxt => apfst the_single (mk_fresh_names ctxt 1 "Asi"))
   1.617 +      ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "i") suc_bdT
   1.618 +      ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "j") suc_bdT
   1.619 +      ||>> mk_Frees "IIB" II_BTs
   1.620 +      ||>> mk_Frees "IIs" II_sTs
   1.621 +      ||>> mk_Frees "f" (map (fn T => Asuc_bdT --> T) activeAs);
   1.622 +
   1.623 +    val suc_bd_limit_thm =
   1.624 +      let
   1.625 +        val prem = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
   1.626 +          (map (fn idx => HOLogic.mk_mem (idx, field_suc_bd)) idxs));
   1.627 +        fun mk_conjunct idx = HOLogic.mk_conj (mk_not_eq idx jdx,
   1.628 +          HOLogic.mk_mem (HOLogic.mk_prod (idx, jdx), suc_bd));
   1.629 +        val concl = HOLogic.mk_Trueprop (mk_Bex field_suc_bd
   1.630 +          (Term.absfree jdx' (Library.foldr1 HOLogic.mk_conj (map mk_conjunct idxs))));
   1.631 +      in
   1.632 +        Goal.prove_sorry lthy [] []
   1.633 +          (fold_rev Logic.all idxs (Logic.list_implies ([prem], concl)))
   1.634 +          (K (mk_bd_limit_tac n suc_bd_Cinfinite))
   1.635 +        |> Thm.close_derivation
   1.636 +      end;
   1.637 +
   1.638 +    val timer = time (timer "Bounds");
   1.639 +
   1.640 +
   1.641 +    (* minimal algebra *)
   1.642 +
   1.643 +    fun mk_minG Asi i k = mk_UNION (mk_underS suc_bd $ i)
   1.644 +      (Term.absfree jdx' (mk_nthN n (Asi $ jdx) k));
   1.645 +
   1.646 +    fun mk_minH_component As Asi i sets Ts s k =
   1.647 +      HOLogic.mk_binop @{const_name "sup"}
   1.648 +      (mk_minG Asi i k, mk_image s $ mk_in (As @ map (mk_minG Asi i) ks) sets Ts);
   1.649 +
   1.650 +    fun mk_min_algs As ss =
   1.651 +      let
   1.652 +        val BTs = map (range_type o fastype_of) ss;
   1.653 +        val Ts = map (HOLogic.dest_setT o fastype_of) As @ BTs;
   1.654 +        val (Asi, Asi') = `Free (Asi_name, suc_bdT -->
   1.655 +          Library.foldr1 HOLogic.mk_prodT (map HOLogic.mk_setT BTs));
   1.656 +      in
   1.657 +         mk_worec suc_bd (Term.absfree Asi' (Term.absfree idx' (HOLogic.mk_tuple
   1.658 +           (map4 (mk_minH_component As Asi idx) (mk_setss Ts) (mk_FTs Ts) ss ks))))
   1.659 +      end;
   1.660 +
   1.661 +    val (min_algs_thms, min_algs_mono_thms, card_of_min_algs_thm, least_min_algs_thm) =
   1.662 +      let
   1.663 +        val i_field = HOLogic.mk_mem (idx, field_suc_bd);
   1.664 +        val min_algs = mk_min_algs As ss;
   1.665 +        val min_algss = map (fn k => mk_nthN n (min_algs $ idx) k) ks;
   1.666 +
   1.667 +        val concl = HOLogic.mk_Trueprop
   1.668 +          (HOLogic.mk_eq (min_algs $ idx, HOLogic.mk_tuple
   1.669 +            (map4 (mk_minH_component As min_algs idx) setssAs FTsAs ss ks)));
   1.670 +        val goal = fold_rev Logic.all (idx :: As @ ss)
   1.671 +          (Logic.mk_implies (HOLogic.mk_Trueprop i_field, concl));
   1.672 +
   1.673 +        val min_algs_thm = Goal.prove_sorry lthy [] [] goal
   1.674 +          (K (mk_min_algs_tac suc_bd_worel in_cong'_thms))
   1.675 +          |> Thm.close_derivation;
   1.676 +
   1.677 +        val min_algs_thms = map (fn k => min_algs_thm RS mk_nthI n k) ks;
   1.678 +
   1.679 +        fun mk_mono_goal min_alg =
   1.680 +          fold_rev Logic.all (As @ ss) (HOLogic.mk_Trueprop (mk_relChain suc_bd
   1.681 +            (Term.absfree idx' min_alg)));
   1.682 +
   1.683 +        val monos =
   1.684 +          map2 (fn goal => fn min_algs =>
   1.685 +            Goal.prove_sorry lthy [] [] goal (K (mk_min_algs_mono_tac lthy min_algs))
   1.686 +            |> Thm.close_derivation)
   1.687 +          (map mk_mono_goal min_algss) min_algs_thms;
   1.688 +
   1.689 +        val Asuc_bd = mk_Asuc_bd As;
   1.690 +
   1.691 +        fun mk_card_conjunct min_alg = mk_ordLeq (mk_card_of min_alg) Asuc_bd;
   1.692 +        val card_conjunction = Library.foldr1 HOLogic.mk_conj (map mk_card_conjunct min_algss);
   1.693 +        val card_cT = certifyT lthy suc_bdT;
   1.694 +        val card_ct = certify lthy (Term.absfree idx' card_conjunction);
   1.695 +
   1.696 +        val card_of = singleton (Proof_Context.export names_lthy lthy)
   1.697 +          (Goal.prove_sorry lthy [] []
   1.698 +            (HOLogic.mk_Trueprop (HOLogic.mk_imp (i_field, card_conjunction)))
   1.699 +            (K (mk_min_algs_card_of_tac card_cT card_ct
   1.700 +              m suc_bd_worel min_algs_thms in_bd_sums
   1.701 +              sum_Card_order sum_Cnotzero suc_bd_Card_order suc_bd_Cinfinite suc_bd_Cnotzero
   1.702 +              suc_bd_Asuc_bd Asuc_bd_Cinfinite)))
   1.703 +          |> Thm.close_derivation;
   1.704 +
   1.705 +        val least_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   1.706 +        val least_conjunction = Library.foldr1 HOLogic.mk_conj (map2 mk_leq min_algss Bs);
   1.707 +        val least_cT = certifyT lthy suc_bdT;
   1.708 +        val least_ct = certify lthy (Term.absfree idx' least_conjunction);
   1.709 +
   1.710 +        val least = singleton (Proof_Context.export names_lthy lthy)
   1.711 +          (Goal.prove_sorry lthy [] []
   1.712 +            (Logic.mk_implies (least_prem,
   1.713 +              HOLogic.mk_Trueprop (HOLogic.mk_imp (i_field, least_conjunction))))
   1.714 +            (K (mk_min_algs_least_tac least_cT least_ct
   1.715 +              suc_bd_worel min_algs_thms alg_set_thms)))
   1.716 +          |> Thm.close_derivation;
   1.717 +      in
   1.718 +        (min_algs_thms, monos, card_of, least)
   1.719 +      end;
   1.720 +
   1.721 +    val timer = time (timer "min_algs definition & thms");
   1.722 +
   1.723 +    val min_alg_binds = mk_internal_bs min_algN;
   1.724 +    fun min_alg_bind i = nth min_alg_binds (i - 1);
   1.725 +    fun min_alg_name i = Binding.name_of (min_alg_bind i);
   1.726 +    val min_alg_def_bind = rpair [] o Thm.def_binding o min_alg_bind;
   1.727 +
   1.728 +    fun min_alg_spec i =
   1.729 +      let
   1.730 +        val min_algT =
   1.731 +          Library.foldr (op -->) (ATs @ sTs, HOLogic.mk_setT (nth activeAs (i - 1)));
   1.732 +
   1.733 +        val lhs = Term.list_comb (Free (min_alg_name i, min_algT), As @ ss);
   1.734 +        val rhs = mk_UNION (field_suc_bd)
   1.735 +          (Term.absfree idx' (mk_nthN n (mk_min_algs As ss $ idx) i));
   1.736 +      in
   1.737 +        mk_Trueprop_eq (lhs, rhs)
   1.738 +      end;
   1.739 +
   1.740 +    val ((min_alg_frees, (_, min_alg_def_frees)), (lthy, lthy_old)) =
   1.741 +        lthy
   1.742 +        |> fold_map (fn i => Specification.definition
   1.743 +          (SOME (min_alg_bind i, NONE, NoSyn), (min_alg_def_bind i, min_alg_spec i))) ks
   1.744 +        |>> apsnd split_list o split_list
   1.745 +        ||> `Local_Theory.restore;
   1.746 +
   1.747 +    val phi = Proof_Context.export_morphism lthy_old lthy;
   1.748 +    val min_algs = map (fst o Term.dest_Const o Morphism.term phi) min_alg_frees;
   1.749 +    val min_alg_defs = map (Morphism.thm phi) min_alg_def_frees;
   1.750 +
   1.751 +    fun mk_min_alg As ss i =
   1.752 +      let
   1.753 +        val T = HOLogic.mk_setT (range_type (fastype_of (nth ss (i - 1))))
   1.754 +        val args = As @ ss;
   1.755 +        val Ts = map fastype_of args;
   1.756 +        val min_algT = Library.foldr (op -->) (Ts, T);
   1.757 +      in
   1.758 +        Term.list_comb (Const (nth min_algs (i - 1), min_algT), args)
   1.759 +      end;
   1.760 +
   1.761 +    val (alg_min_alg_thm, card_of_min_alg_thms, least_min_alg_thms, mor_incl_min_alg_thm) =
   1.762 +      let
   1.763 +        val min_algs = map (mk_min_alg As ss) ks;
   1.764 +
   1.765 +        val goal = fold_rev Logic.all (As @ ss) (HOLogic.mk_Trueprop (mk_alg As min_algs ss));
   1.766 +        val alg_min_alg = Goal.prove_sorry lthy [] [] goal
   1.767 +          (K (mk_alg_min_alg_tac m alg_def min_alg_defs suc_bd_limit_thm sum_Cinfinite
   1.768 +            set_bd_sumss min_algs_thms min_algs_mono_thms))
   1.769 +          |> Thm.close_derivation;
   1.770 +
   1.771 +        val Asuc_bd = mk_Asuc_bd As;
   1.772 +        fun mk_card_of_thm min_alg def = Goal.prove_sorry lthy [] []
   1.773 +          (fold_rev Logic.all (As @ ss)
   1.774 +            (HOLogic.mk_Trueprop (mk_ordLeq (mk_card_of min_alg) Asuc_bd)))
   1.775 +          (K (mk_card_of_min_alg_tac def card_of_min_algs_thm
   1.776 +            suc_bd_Card_order suc_bd_Asuc_bd Asuc_bd_Cinfinite))
   1.777 +          |> Thm.close_derivation;
   1.778 +
   1.779 +        val least_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   1.780 +        fun mk_least_thm min_alg B def = Goal.prove_sorry lthy [] []
   1.781 +          (fold_rev Logic.all (As @ Bs @ ss)
   1.782 +            (Logic.mk_implies (least_prem, HOLogic.mk_Trueprop (mk_leq min_alg B))))
   1.783 +          (K (mk_least_min_alg_tac def least_min_algs_thm))
   1.784 +          |> Thm.close_derivation;
   1.785 +
   1.786 +        val leasts = map3 mk_least_thm min_algs Bs min_alg_defs;
   1.787 +
   1.788 +        val incl_prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   1.789 +        val incl_min_algs = map (mk_min_alg passive_UNIVs ss) ks;
   1.790 +        val incl = Goal.prove_sorry lthy [] []
   1.791 +          (fold_rev Logic.all (Bs @ ss)
   1.792 +            (Logic.mk_implies (incl_prem,
   1.793 +              HOLogic.mk_Trueprop (mk_mor incl_min_algs ss Bs ss active_ids))))
   1.794 +          (K (EVERY' (rtac mor_incl_thm :: map etac leasts) 1))
   1.795 +          |> Thm.close_derivation;
   1.796 +      in
   1.797 +        (alg_min_alg, map2 mk_card_of_thm min_algs min_alg_defs, leasts, incl)
   1.798 +      end;
   1.799 +
   1.800 +    val timer = time (timer "Minimal algebra definition & thms");
   1.801 +
   1.802 +    val II_repT = HOLogic.mk_prodT (HOLogic.mk_tupleT II_BTs, HOLogic.mk_tupleT II_sTs);
   1.803 +    val IIT_bind = mk_internal_b IITN;
   1.804 +
   1.805 +    val ((IIT_name, (IIT_glob_info, IIT_loc_info)), lthy) =
   1.806 +      typedef (IIT_bind, params, NoSyn)
   1.807 +        (HOLogic.mk_UNIV II_repT) NONE (EVERY' [rtac exI, rtac UNIV_I] 1) lthy;
   1.808 +
   1.809 +    val IIT = Type (IIT_name, params');
   1.810 +    val Abs_IIT = Const (#Abs_name IIT_glob_info, II_repT --> IIT);
   1.811 +    val Rep_IIT = Const (#Rep_name IIT_glob_info, IIT --> II_repT);
   1.812 +    val Abs_IIT_inverse_thm = UNIV_I RS #Abs_inverse IIT_loc_info;
   1.813 +
   1.814 +    val initT = IIT --> Asuc_bdT;
   1.815 +    val active_initTs = replicate n initT;
   1.816 +    val init_FTs = map2 (fn Ds => mk_T_of_bnf Ds (passiveAs @ active_initTs)) Dss bnfs;
   1.817 +    val init_fTs = map (fn T => initT --> T) activeAs;
   1.818 +
   1.819 +    val (((((((iidx, iidx'), init_xs), (init_xFs, init_xFs')),
   1.820 +      init_fs), init_fs_copy), init_phis), names_lthy) = names_lthy
   1.821 +      |> yield_singleton (apfst (op ~~) oo mk_Frees' "i") IIT
   1.822 +      ||>> mk_Frees "ix" active_initTs
   1.823 +      ||>> mk_Frees' "x" init_FTs
   1.824 +      ||>> mk_Frees "f" init_fTs
   1.825 +      ||>> mk_Frees "f" init_fTs
   1.826 +      ||>> mk_Frees "P" (replicate n (mk_pred1T initT));
   1.827 +
   1.828 +    val II = HOLogic.mk_Collect (fst iidx', IIT, list_exists_free (II_Bs @ II_ss)
   1.829 +      (HOLogic.mk_conj (HOLogic.mk_eq (iidx,
   1.830 +        Abs_IIT $ (HOLogic.mk_prod (HOLogic.mk_tuple II_Bs, HOLogic.mk_tuple II_ss))),
   1.831 +        mk_alg passive_UNIVs II_Bs II_ss)));
   1.832 +
   1.833 +    val select_Bs = map (mk_nthN n (HOLogic.mk_fst (Rep_IIT $ iidx))) ks;
   1.834 +    val select_ss = map (mk_nthN n (HOLogic.mk_snd (Rep_IIT $ iidx))) ks;
   1.835 +
   1.836 +    val str_init_binds = mk_internal_bs str_initN;
   1.837 +    fun str_init_bind i = nth str_init_binds (i - 1);
   1.838 +    val str_init_name = Binding.name_of o str_init_bind;
   1.839 +    val str_init_def_bind = rpair [] o Thm.def_binding o str_init_bind;
   1.840 +
   1.841 +    fun str_init_spec i =
   1.842 +      let
   1.843 +        val T = nth init_FTs (i - 1);
   1.844 +        val init_xF = nth init_xFs (i - 1)
   1.845 +        val select_s = nth select_ss (i - 1);
   1.846 +        val map = mk_map_of_bnf (nth Dss (i - 1))
   1.847 +          (passiveAs @ active_initTs) (passiveAs @ replicate n Asuc_bdT)
   1.848 +          (nth bnfs (i - 1));
   1.849 +        val map_args = passive_ids @ replicate n (mk_rapp iidx Asuc_bdT);
   1.850 +        val str_initT = T --> IIT --> Asuc_bdT;
   1.851 +
   1.852 +        val lhs = Term.list_comb (Free (str_init_name i, str_initT), [init_xF, iidx]);
   1.853 +        val rhs = select_s $ (Term.list_comb (map, map_args) $ init_xF);
   1.854 +      in
   1.855 +        mk_Trueprop_eq (lhs, rhs)
   1.856 +      end;
   1.857 +
   1.858 +    val ((str_init_frees, (_, str_init_def_frees)), (lthy, lthy_old)) =
   1.859 +      lthy
   1.860 +      |> fold_map (fn i => Specification.definition
   1.861 +        (SOME (str_init_bind i, NONE, NoSyn), (str_init_def_bind i, str_init_spec i))) ks
   1.862 +      |>> apsnd split_list o split_list
   1.863 +      ||> `Local_Theory.restore;
   1.864 +
   1.865 +    val phi = Proof_Context.export_morphism lthy_old lthy;
   1.866 +    val str_inits =
   1.867 +      map (Term.subst_atomic_types (map (`(Morphism.typ phi)) params') o Morphism.term phi)
   1.868 +        str_init_frees;
   1.869 +
   1.870 +    val str_init_defs = map (Morphism.thm phi) str_init_def_frees;
   1.871 +
   1.872 +    val car_inits = map (mk_min_alg passive_UNIVs str_inits) ks;
   1.873 +
   1.874 +    (*TODO: replace with instantiate? (problem: figure out right type instantiation)*)
   1.875 +    val alg_init_thm = Goal.prove_sorry lthy [] []
   1.876 +      (HOLogic.mk_Trueprop (mk_alg passive_UNIVs car_inits str_inits))
   1.877 +      (K (rtac alg_min_alg_thm 1))
   1.878 +      |> Thm.close_derivation;
   1.879 +
   1.880 +    val alg_select_thm = Goal.prove_sorry lthy [] []
   1.881 +      (HOLogic.mk_Trueprop (mk_Ball II
   1.882 +        (Term.absfree iidx' (mk_alg passive_UNIVs select_Bs select_ss))))
   1.883 +      (mk_alg_select_tac Abs_IIT_inverse_thm)
   1.884 +      |> Thm.close_derivation;
   1.885 +
   1.886 +    val mor_select_thm =
   1.887 +      let
   1.888 +        val alg_prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   1.889 +        val i_prem = HOLogic.mk_Trueprop (HOLogic.mk_mem (iidx, II));
   1.890 +        val mor_prem = HOLogic.mk_Trueprop (mk_mor select_Bs select_ss Bs ss Asuc_fs);
   1.891 +        val prems = [alg_prem, i_prem, mor_prem];
   1.892 +        val concl = HOLogic.mk_Trueprop
   1.893 +          (mk_mor car_inits str_inits Bs ss
   1.894 +            (map (fn f => HOLogic.mk_comp (f, mk_rapp iidx Asuc_bdT)) Asuc_fs));
   1.895 +      in
   1.896 +        Goal.prove_sorry lthy [] []
   1.897 +          (fold_rev Logic.all (iidx :: Bs @ ss @ Asuc_fs) (Logic.list_implies (prems, concl)))
   1.898 +          (K (mk_mor_select_tac mor_def mor_cong_thm mor_comp_thm mor_incl_min_alg_thm alg_def
   1.899 +            alg_select_thm alg_set_thms set_mapss str_init_defs))
   1.900 +        |> Thm.close_derivation
   1.901 +      end;
   1.902 +
   1.903 +    val (init_ex_mor_thm, init_unique_mor_thms) =
   1.904 +      let
   1.905 +        val prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   1.906 +        val concl = HOLogic.mk_Trueprop
   1.907 +          (list_exists_free init_fs (mk_mor car_inits str_inits Bs ss init_fs));
   1.908 +        val ex_mor = Goal.prove_sorry lthy [] []
   1.909 +          (fold_rev Logic.all (Bs @ ss) (Logic.mk_implies (prem, concl)))
   1.910 +          (mk_init_ex_mor_tac Abs_IIT_inverse_thm ex_copy_alg_thm alg_min_alg_thm
   1.911 +            card_of_min_alg_thms mor_comp_thm mor_select_thm mor_incl_min_alg_thm)
   1.912 +          |> Thm.close_derivation;
   1.913 +
   1.914 +        val prems = map2 (HOLogic.mk_Trueprop oo curry HOLogic.mk_mem) init_xs car_inits
   1.915 +        val mor_prems = map HOLogic.mk_Trueprop
   1.916 +          [mk_mor car_inits str_inits Bs ss init_fs,
   1.917 +          mk_mor car_inits str_inits Bs ss init_fs_copy];
   1.918 +        fun mk_fun_eq f g x = HOLogic.mk_eq (f $ x, g $ x);
   1.919 +        val unique = HOLogic.mk_Trueprop
   1.920 +          (Library.foldr1 HOLogic.mk_conj (map3 mk_fun_eq init_fs init_fs_copy init_xs));
   1.921 +        val unique_mor = Goal.prove_sorry lthy [] []
   1.922 +          (fold_rev Logic.all (init_xs @ Bs @ ss @ init_fs @ init_fs_copy)
   1.923 +            (Logic.list_implies (prems @ mor_prems, unique)))
   1.924 +          (K (mk_init_unique_mor_tac m alg_def alg_init_thm least_min_alg_thms
   1.925 +            in_mono'_thms alg_set_thms morE_thms map_cong0s))
   1.926 +          |> Thm.close_derivation;
   1.927 +      in
   1.928 +        (ex_mor, split_conj_thm unique_mor)
   1.929 +      end;
   1.930 +
   1.931 +    val init_setss = mk_setss (passiveAs @ active_initTs);
   1.932 +    val active_init_setss = map (drop m) init_setss;
   1.933 +    val init_ins = map2 (fn sets => mk_in (passive_UNIVs @ car_inits) sets) init_setss init_FTs;
   1.934 +
   1.935 +    fun mk_closed phis =
   1.936 +      let
   1.937 +        fun mk_conjunct phi str_init init_sets init_in x x' =
   1.938 +          let
   1.939 +            val prem = Library.foldr1 HOLogic.mk_conj
   1.940 +              (map2 (fn set => mk_Ball (set $ x)) init_sets phis);
   1.941 +            val concl = phi $ (str_init $ x);
   1.942 +          in
   1.943 +            mk_Ball init_in (Term.absfree x' (HOLogic.mk_imp (prem, concl)))
   1.944 +          end;
   1.945 +      in
   1.946 +        Library.foldr1 HOLogic.mk_conj
   1.947 +          (map6 mk_conjunct phis str_inits active_init_setss init_ins init_xFs init_xFs')
   1.948 +      end;
   1.949 +
   1.950 +    val init_induct_thm =
   1.951 +      let
   1.952 +        val prem = HOLogic.mk_Trueprop (mk_closed init_phis);
   1.953 +        val concl = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
   1.954 +          (map2 mk_Ball car_inits init_phis));
   1.955 +      in
   1.956 +        Goal.prove_sorry lthy [] []
   1.957 +          (fold_rev Logic.all init_phis (Logic.mk_implies (prem, concl)))
   1.958 +          (K (mk_init_induct_tac m alg_def alg_init_thm least_min_alg_thms alg_set_thms))
   1.959 +        |> Thm.close_derivation
   1.960 +      end;
   1.961 +
   1.962 +    val timer = time (timer "Initiality definition & thms");
   1.963 +
   1.964 +    val ((T_names, (T_glob_infos, T_loc_infos)), lthy) =
   1.965 +      lthy
   1.966 +      |> fold_map3 (fn b => fn mx => fn car_init =>
   1.967 +        typedef (Binding.conceal b, params, mx) car_init NONE
   1.968 +          (EVERY' [rtac ssubst, rtac @{thm ex_in_conv}, resolve_tac alg_not_empty_thms,
   1.969 +            rtac alg_init_thm] 1)) bs mixfixes car_inits
   1.970 +      |>> apsnd split_list o split_list;
   1.971 +
   1.972 +    val Ts = map (fn name => Type (name, params')) T_names;
   1.973 +    fun mk_Ts passive = map (Term.typ_subst_atomic (passiveAs ~~ passive)) Ts;
   1.974 +    val Ts' = mk_Ts passiveBs;
   1.975 +    val Rep_Ts = map2 (fn info => fn T => Const (#Rep_name info, T --> initT)) T_glob_infos Ts;
   1.976 +    val Abs_Ts = map2 (fn info => fn T => Const (#Abs_name info, initT --> T)) T_glob_infos Ts;
   1.977 +
   1.978 +    val type_defs = map #type_definition T_loc_infos;
   1.979 +    val Reps = map #Rep T_loc_infos;
   1.980 +    val Rep_casess = map #Rep_cases T_loc_infos;
   1.981 +    val Rep_injects = map #Rep_inject T_loc_infos;
   1.982 +    val Rep_inverses = map #Rep_inverse T_loc_infos;
   1.983 +    val Abs_inverses = map #Abs_inverse T_loc_infos;
   1.984 +
   1.985 +    fun mk_inver_thm mk_tac rep abs X thm =
   1.986 +      Goal.prove_sorry lthy [] []
   1.987 +        (HOLogic.mk_Trueprop (mk_inver rep abs X))
   1.988 +        (K (EVERY' [rtac ssubst, rtac @{thm inver_def}, rtac ballI, mk_tac thm] 1))
   1.989 +      |> Thm.close_derivation;
   1.990 +
   1.991 +    val inver_Reps = map4 (mk_inver_thm rtac) Abs_Ts Rep_Ts (map HOLogic.mk_UNIV Ts) Rep_inverses;
   1.992 +    val inver_Abss = map4 (mk_inver_thm etac) Rep_Ts Abs_Ts car_inits Abs_inverses;
   1.993 +
   1.994 +    val timer = time (timer "THE TYPEDEFs & Rep/Abs thms");
   1.995 +
   1.996 +    val UNIVs = map HOLogic.mk_UNIV Ts;
   1.997 +    val FTs = mk_FTs (passiveAs @ Ts);
   1.998 +    val FTs' = mk_FTs (passiveBs @ Ts');
   1.999 +    fun mk_set_Ts T = passiveAs @ replicate n (HOLogic.mk_setT T);
  1.1000 +    val setFTss = map (mk_FTs o mk_set_Ts) passiveAs;
  1.1001 +    val FTs_setss = mk_setss (passiveAs @ Ts);
  1.1002 +    val FTs'_setss = mk_setss (passiveBs @ Ts');
  1.1003 +    val map_FT_inits = map2 (fn Ds =>
  1.1004 +      mk_map_of_bnf Ds (passiveAs @ Ts) (passiveAs @ active_initTs)) Dss bnfs;
  1.1005 +    val fTs = map2 (curry op -->) Ts activeAs;
  1.1006 +    val foldT = Library.foldr1 HOLogic.mk_prodT (map2 (curry op -->) Ts activeAs);
  1.1007 +    val rec_sTs = map (Term.typ_subst_atomic (activeBs ~~ Ts)) prod_sTs;
  1.1008 +    val rec_maps = map (Term.subst_atomic_types (activeBs ~~ Ts)) map_fsts;
  1.1009 +    val rec_maps_rev = map (Term.subst_atomic_types (activeBs ~~ Ts)) map_fsts_rev;
  1.1010 +    val rec_fsts = map (Term.subst_atomic_types (activeBs ~~ Ts)) fsts;
  1.1011 +    val rec_UNIVs = map2 (HOLogic.mk_UNIV oo curry HOLogic.mk_prodT) Ts activeAs;
  1.1012 +
  1.1013 +    val (((((((((Izs1, Izs1'), (Izs2, Izs2')), (xFs, xFs')), yFs), (AFss, AFss')),
  1.1014 +      (fold_f, fold_f')), fs), rec_ss), names_lthy) = names_lthy
  1.1015 +      |> mk_Frees' "z1" Ts
  1.1016 +      ||>> mk_Frees' "z2" Ts'
  1.1017 +      ||>> mk_Frees' "x" FTs
  1.1018 +      ||>> mk_Frees "y" FTs'
  1.1019 +      ||>> mk_Freess' "z" setFTss
  1.1020 +      ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "f") foldT
  1.1021 +      ||>> mk_Frees "f" fTs
  1.1022 +      ||>> mk_Frees "s" rec_sTs;
  1.1023 +
  1.1024 +    val Izs = map2 retype_free Ts zs;
  1.1025 +    val phis = map2 retype_free (map mk_pred1T Ts) init_phis;
  1.1026 +    val phi2s = map2 retype_free (map2 mk_pred2T Ts Ts') init_phis;
  1.1027 +
  1.1028 +    fun ctor_bind i = nth external_bs (i - 1) |> Binding.prefix_name (ctorN ^ "_");
  1.1029 +    val ctor_name = Binding.name_of o ctor_bind;
  1.1030 +    val ctor_def_bind = rpair [] o Binding.conceal o Thm.def_binding o ctor_bind;
  1.1031 +
  1.1032 +    fun ctor_spec i abs str map_FT_init x x' =
  1.1033 +      let
  1.1034 +        val ctorT = nth FTs (i - 1) --> nth Ts (i - 1);
  1.1035 +
  1.1036 +        val lhs = Free (ctor_name i, ctorT);
  1.1037 +        val rhs = Term.absfree x' (abs $ (str $
  1.1038 +          (Term.list_comb (map_FT_init, map HOLogic.id_const passiveAs @ Rep_Ts) $ x)));
  1.1039 +      in
  1.1040 +        mk_Trueprop_eq (lhs, rhs)
  1.1041 +      end;
  1.1042 +
  1.1043 +    val ((ctor_frees, (_, ctor_def_frees)), (lthy, lthy_old)) =
  1.1044 +      lthy
  1.1045 +      |> fold_map6 (fn i => fn abs => fn str => fn mapx => fn x => fn x' =>
  1.1046 +        Specification.definition
  1.1047 +          (SOME (ctor_bind i, NONE, NoSyn), (ctor_def_bind i, ctor_spec i abs str mapx x x')))
  1.1048 +          ks Abs_Ts str_inits map_FT_inits xFs xFs'
  1.1049 +      |>> apsnd split_list o split_list
  1.1050 +      ||> `Local_Theory.restore;
  1.1051 +
  1.1052 +    val phi = Proof_Context.export_morphism lthy_old lthy;
  1.1053 +    fun mk_ctors passive =
  1.1054 +      map (Term.subst_atomic_types (map (Morphism.typ phi) params' ~~ (mk_params passive)) o
  1.1055 +        Morphism.term phi) ctor_frees;
  1.1056 +    val ctors = mk_ctors passiveAs;
  1.1057 +    val ctor's = mk_ctors passiveBs;
  1.1058 +    val ctor_defs = map (Morphism.thm phi) ctor_def_frees;
  1.1059 +
  1.1060 +    val (mor_Rep_thm, mor_Abs_thm) =
  1.1061 +      let
  1.1062 +        val copy = alg_init_thm RS copy_alg_thm;
  1.1063 +        fun mk_bij inj Rep cases = @{thm bij_betwI'} OF [inj, Rep, cases];
  1.1064 +        val bijs = map3 mk_bij Rep_injects Reps Rep_casess;
  1.1065 +        val mor_Rep =
  1.1066 +          Goal.prove_sorry lthy [] []
  1.1067 +            (HOLogic.mk_Trueprop (mk_mor UNIVs ctors car_inits str_inits Rep_Ts))
  1.1068 +            (mk_mor_Rep_tac ctor_defs copy bijs inver_Abss inver_Reps)
  1.1069 +          |> Thm.close_derivation;
  1.1070 +
  1.1071 +        val inv = mor_inv_thm OF [mor_Rep, talg_thm, alg_init_thm];
  1.1072 +        val mor_Abs =
  1.1073 +          Goal.prove_sorry lthy [] []
  1.1074 +            (HOLogic.mk_Trueprop (mk_mor car_inits str_inits UNIVs ctors Abs_Ts))
  1.1075 +            (K (mk_mor_Abs_tac inv inver_Abss inver_Reps))
  1.1076 +          |> Thm.close_derivation;
  1.1077 +      in
  1.1078 +        (mor_Rep, mor_Abs)
  1.1079 +      end;
  1.1080 +
  1.1081 +    val timer = time (timer "ctor definitions & thms");
  1.1082 +
  1.1083 +    val fold_fun = Term.absfree fold_f'
  1.1084 +      (mk_mor UNIVs ctors active_UNIVs ss (map (mk_nthN n fold_f) ks));
  1.1085 +    val foldx = HOLogic.choice_const foldT $ fold_fun;
  1.1086 +
  1.1087 +    fun fold_bind i = nth external_bs (i - 1) |> Binding.prefix_name (ctor_foldN ^ "_");
  1.1088 +    val fold_name = Binding.name_of o fold_bind;
  1.1089 +    val fold_def_bind = rpair [] o Binding.conceal o Thm.def_binding o fold_bind;
  1.1090 +
  1.1091 +    fun fold_spec i T AT =
  1.1092 +      let
  1.1093 +        val foldT = Library.foldr (op -->) (sTs, T --> AT);
  1.1094 +
  1.1095 +        val lhs = Term.list_comb (Free (fold_name i, foldT), ss);
  1.1096 +        val rhs = mk_nthN n foldx i;
  1.1097 +      in
  1.1098 +        mk_Trueprop_eq (lhs, rhs)
  1.1099 +      end;
  1.1100 +
  1.1101 +    val ((fold_frees, (_, fold_def_frees)), (lthy, lthy_old)) =
  1.1102 +      lthy
  1.1103 +      |> fold_map3 (fn i => fn T => fn AT =>
  1.1104 +        Specification.definition
  1.1105 +          (SOME (fold_bind i, NONE, NoSyn), (fold_def_bind i, fold_spec i T AT)))
  1.1106 +          ks Ts activeAs
  1.1107 +      |>> apsnd split_list o split_list
  1.1108 +      ||> `Local_Theory.restore;
  1.1109 +
  1.1110 +    val phi = Proof_Context.export_morphism lthy_old lthy;
  1.1111 +    val folds = map (Morphism.term phi) fold_frees;
  1.1112 +    val fold_names = map (fst o dest_Const) folds;
  1.1113 +    fun mk_folds passives actives =
  1.1114 +      map3 (fn name => fn T => fn active =>
  1.1115 +        Const (name, Library.foldr (op -->)
  1.1116 +          (map2 (curry op -->) (mk_FTs (passives @ actives)) actives, T --> active)))
  1.1117 +      fold_names (mk_Ts passives) actives;
  1.1118 +    fun mk_fold Ts ss i = Term.list_comb (Const (nth fold_names (i - 1), Library.foldr (op -->)
  1.1119 +      (map fastype_of ss, nth Ts (i - 1) --> range_type (fastype_of (nth ss (i - 1))))), ss);
  1.1120 +    val fold_defs = map (Morphism.thm phi) fold_def_frees;
  1.1121 +
  1.1122 +    val mor_fold_thm =
  1.1123 +      let
  1.1124 +        val ex_mor = talg_thm RS init_ex_mor_thm;
  1.1125 +        val mor_cong = mor_cong_thm OF (map (mk_nth_conv n) ks);
  1.1126 +        val mor_comp = mor_Rep_thm RS mor_comp_thm;
  1.1127 +        val cT = certifyT lthy foldT;
  1.1128 +        val ct = certify lthy fold_fun
  1.1129 +      in
  1.1130 +        singleton (Proof_Context.export names_lthy lthy)
  1.1131 +          (Goal.prove_sorry lthy [] []
  1.1132 +            (HOLogic.mk_Trueprop (mk_mor UNIVs ctors active_UNIVs ss (map (mk_fold Ts ss) ks)))
  1.1133 +            (K (mk_mor_fold_tac cT ct fold_defs ex_mor (mor_comp RS mor_cong))))
  1.1134 +        |> Thm.close_derivation
  1.1135 +      end;
  1.1136 +
  1.1137 +    val ctor_fold_thms = map (fn morE => rule_by_tactic lthy
  1.1138 +      ((rtac CollectI THEN' CONJ_WRAP' (K (rtac @{thm subset_UNIV})) (1 upto m + n)) 1)
  1.1139 +      (mor_fold_thm RS morE)) morE_thms;
  1.1140 +
  1.1141 +    val (fold_unique_mor_thms, fold_unique_mor_thm) =
  1.1142 +      let
  1.1143 +        val prem = HOLogic.mk_Trueprop (mk_mor UNIVs ctors active_UNIVs ss fs);
  1.1144 +        fun mk_fun_eq f i = HOLogic.mk_eq (f, mk_fold Ts ss i);
  1.1145 +        val unique = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_fun_eq fs ks));
  1.1146 +        val unique_mor = Goal.prove_sorry lthy [] []
  1.1147 +          (fold_rev Logic.all (ss @ fs) (Logic.mk_implies (prem, unique)))
  1.1148 +          (K (mk_fold_unique_mor_tac type_defs init_unique_mor_thms Reps
  1.1149 +            mor_comp_thm mor_Abs_thm mor_fold_thm))
  1.1150 +          |> Thm.close_derivation;
  1.1151 +      in
  1.1152 +        `split_conj_thm unique_mor
  1.1153 +      end;
  1.1154 +
  1.1155 +    val (ctor_fold_unique_thms, ctor_fold_unique_thm) =
  1.1156 +      `split_conj_thm (mk_conjIN n RS
  1.1157 +        (mor_UNIV_thm RS iffD2 RS fold_unique_mor_thm))
  1.1158 +
  1.1159 +    val fold_ctor_thms =
  1.1160 +      map (fn thm => (mor_incl_thm OF replicate n @{thm subset_UNIV}) RS thm RS sym)
  1.1161 +        fold_unique_mor_thms;
  1.1162 +
  1.1163 +    val ctor_o_fold_thms =
  1.1164 +      let
  1.1165 +        val mor = mor_comp_thm OF [mor_fold_thm, mor_str_thm];
  1.1166 +      in
  1.1167 +        map2 (fn unique => fn fold_ctor =>
  1.1168 +          trans OF [mor RS unique, fold_ctor]) fold_unique_mor_thms fold_ctor_thms
  1.1169 +      end;
  1.1170 +
  1.1171 +    val timer = time (timer "fold definitions & thms");
  1.1172 +
  1.1173 +    val map_ctors = map2 (fn Ds => fn bnf =>
  1.1174 +      Term.list_comb (mk_map_of_bnf Ds (passiveAs @ FTs) (passiveAs @ Ts) bnf,
  1.1175 +        map HOLogic.id_const passiveAs @ ctors)) Dss bnfs;
  1.1176 +
  1.1177 +    fun dtor_bind i = nth external_bs (i - 1) |> Binding.prefix_name (dtorN ^ "_");
  1.1178 +    val dtor_name = Binding.name_of o dtor_bind;
  1.1179 +    val dtor_def_bind = rpair [] o Binding.conceal o Thm.def_binding o dtor_bind;
  1.1180 +
  1.1181 +    fun dtor_spec i FT T =
  1.1182 +      let
  1.1183 +        val dtorT = T --> FT;
  1.1184 +
  1.1185 +        val lhs = Free (dtor_name i, dtorT);
  1.1186 +        val rhs = mk_fold Ts map_ctors i;
  1.1187 +      in
  1.1188 +        mk_Trueprop_eq (lhs, rhs)
  1.1189 +      end;
  1.1190 +
  1.1191 +    val ((dtor_frees, (_, dtor_def_frees)), (lthy, lthy_old)) =
  1.1192 +      lthy
  1.1193 +      |> fold_map3 (fn i => fn FT => fn T =>
  1.1194 +        Specification.definition
  1.1195 +          (SOME (dtor_bind i, NONE, NoSyn), (dtor_def_bind i, dtor_spec i FT T))) ks FTs Ts
  1.1196 +      |>> apsnd split_list o split_list
  1.1197 +      ||> `Local_Theory.restore;
  1.1198 +
  1.1199 +    val phi = Proof_Context.export_morphism lthy_old lthy;
  1.1200 +    fun mk_dtors params =
  1.1201 +      map (Term.subst_atomic_types (map (Morphism.typ phi) params' ~~ params) o Morphism.term phi)
  1.1202 +        dtor_frees;
  1.1203 +    val dtors = mk_dtors params';
  1.1204 +    val dtor_defs = map (Morphism.thm phi) dtor_def_frees;
  1.1205 +
  1.1206 +    val ctor_o_dtor_thms = map2 (fold_thms lthy o single) dtor_defs ctor_o_fold_thms;
  1.1207 +
  1.1208 +    val dtor_o_ctor_thms =
  1.1209 +      let
  1.1210 +        fun mk_goal dtor ctor FT =
  1.1211 +          mk_Trueprop_eq (HOLogic.mk_comp (dtor, ctor), HOLogic.id_const FT);
  1.1212 +        val goals = map3 mk_goal dtors ctors FTs;
  1.1213 +      in
  1.1214 +        map5 (fn goal => fn dtor_def => fn foldx => fn map_comp_id => fn map_cong0L =>
  1.1215 +          Goal.prove_sorry lthy [] [] goal
  1.1216 +            (K (mk_dtor_o_ctor_tac dtor_def foldx map_comp_id map_cong0L ctor_o_fold_thms))
  1.1217 +          |> Thm.close_derivation)
  1.1218 +        goals dtor_defs ctor_fold_thms map_comp_id_thms map_cong0L_thms
  1.1219 +      end;
  1.1220 +
  1.1221 +    val dtor_ctor_thms = map (fn thm => thm RS @{thm pointfree_idE}) dtor_o_ctor_thms;
  1.1222 +    val ctor_dtor_thms = map (fn thm => thm RS @{thm pointfree_idE}) ctor_o_dtor_thms;
  1.1223 +
  1.1224 +    val bij_dtor_thms =
  1.1225 +      map2 (fn thm1 => fn thm2 => @{thm o_bij} OF [thm1, thm2]) ctor_o_dtor_thms dtor_o_ctor_thms;
  1.1226 +    val inj_dtor_thms = map (fn thm => thm RS @{thm bij_is_inj}) bij_dtor_thms;
  1.1227 +    val surj_dtor_thms = map (fn thm => thm RS @{thm bij_is_surj}) bij_dtor_thms;
  1.1228 +    val dtor_nchotomy_thms = map (fn thm => thm RS @{thm surjD}) surj_dtor_thms;
  1.1229 +    val dtor_inject_thms = map (fn thm => thm RS @{thm inj_eq}) inj_dtor_thms;
  1.1230 +    val dtor_exhaust_thms = map (fn thm => thm RS exE) dtor_nchotomy_thms;
  1.1231 +
  1.1232 +    val bij_ctor_thms =
  1.1233 +      map2 (fn thm1 => fn thm2 => @{thm o_bij} OF [thm1, thm2]) dtor_o_ctor_thms ctor_o_dtor_thms;
  1.1234 +    val inj_ctor_thms = map (fn thm => thm RS @{thm bij_is_inj}) bij_ctor_thms;
  1.1235 +    val surj_ctor_thms = map (fn thm => thm RS @{thm bij_is_surj}) bij_ctor_thms;
  1.1236 +    val ctor_nchotomy_thms = map (fn thm => thm RS @{thm surjD}) surj_ctor_thms;
  1.1237 +    val ctor_inject_thms = map (fn thm => thm RS @{thm inj_eq}) inj_ctor_thms;
  1.1238 +    val ctor_exhaust_thms = map (fn thm => thm RS exE) ctor_nchotomy_thms;
  1.1239 +
  1.1240 +    val timer = time (timer "dtor definitions & thms");
  1.1241 +
  1.1242 +    val fst_rec_pair_thms =
  1.1243 +      let
  1.1244 +        val mor = mor_comp_thm OF [mor_fold_thm, mor_convol_thm];
  1.1245 +      in
  1.1246 +        map2 (fn unique => fn fold_ctor =>
  1.1247 +          trans OF [mor RS unique, fold_ctor]) fold_unique_mor_thms fold_ctor_thms
  1.1248 +      end;
  1.1249 +
  1.1250 +    fun rec_bind i = nth external_bs (i - 1) |> Binding.prefix_name (ctor_recN ^ "_");
  1.1251 +    val rec_name = Binding.name_of o rec_bind;
  1.1252 +    val rec_def_bind = rpair [] o Binding.conceal o Thm.def_binding o rec_bind;
  1.1253 +
  1.1254 +    val rec_strs =
  1.1255 +      map3 (fn ctor => fn prod_s => fn mapx =>
  1.1256 +        mk_convol (HOLogic.mk_comp (ctor, Term.list_comb (mapx, passive_ids @ rec_fsts)), prod_s))
  1.1257 +      ctors rec_ss rec_maps;
  1.1258 +
  1.1259 +    fun rec_spec i T AT =
  1.1260 +      let
  1.1261 +        val recT = Library.foldr (op -->) (rec_sTs, T --> AT);
  1.1262 +
  1.1263 +        val lhs = Term.list_comb (Free (rec_name i, recT), rec_ss);
  1.1264 +        val rhs = HOLogic.mk_comp (snd_const (HOLogic.mk_prodT (T, AT)), mk_fold Ts rec_strs i);
  1.1265 +      in
  1.1266 +        mk_Trueprop_eq (lhs, rhs)
  1.1267 +      end;
  1.1268 +
  1.1269 +    val ((rec_frees, (_, rec_def_frees)), (lthy, lthy_old)) =
  1.1270 +      lthy
  1.1271 +      |> fold_map3 (fn i => fn T => fn AT =>
  1.1272 +        Specification.definition
  1.1273 +          (SOME (rec_bind i, NONE, NoSyn), (rec_def_bind i, rec_spec i T AT)))
  1.1274 +          ks Ts activeAs
  1.1275 +      |>> apsnd split_list o split_list
  1.1276 +      ||> `Local_Theory.restore;
  1.1277 +
  1.1278 +    val phi = Proof_Context.export_morphism lthy_old lthy;
  1.1279 +    val recs = map (Morphism.term phi) rec_frees;
  1.1280 +    val rec_names = map (fst o dest_Const) recs;
  1.1281 +    fun mk_rec ss i = Term.list_comb (Const (nth rec_names (i - 1), Library.foldr (op -->)
  1.1282 +      (map fastype_of ss, nth Ts (i - 1) --> range_type (fastype_of (nth ss (i - 1))))), ss);
  1.1283 +    val rec_defs = map (Morphism.thm phi) rec_def_frees;
  1.1284 +
  1.1285 +    val convols = map2 (fn T => fn i => mk_convol (HOLogic.id_const T, mk_rec rec_ss i)) Ts ks;
  1.1286 +    val ctor_rec_thms =
  1.1287 +      let
  1.1288 +        fun mk_goal i rec_s rec_map ctor x =
  1.1289 +          let
  1.1290 +            val lhs = mk_rec rec_ss i $ (ctor $ x);
  1.1291 +            val rhs = rec_s $ (Term.list_comb (rec_map, passive_ids @ convols) $ x);
  1.1292 +          in
  1.1293 +            fold_rev Logic.all (x :: rec_ss) (mk_Trueprop_eq (lhs, rhs))
  1.1294 +          end;
  1.1295 +        val goals = map5 mk_goal ks rec_ss rec_maps_rev ctors xFs;
  1.1296 +      in
  1.1297 +        map2 (fn goal => fn foldx =>
  1.1298 +          Goal.prove_sorry lthy [] [] goal (mk_rec_tac rec_defs foldx fst_rec_pair_thms)
  1.1299 +          |> Thm.close_derivation)
  1.1300 +        goals ctor_fold_thms
  1.1301 +      end;
  1.1302 +
  1.1303 +    val rec_unique_mor_thm =
  1.1304 +      let
  1.1305 +        val id_fs = map2 (fn T => fn f => mk_convol (HOLogic.id_const T, f)) Ts fs;
  1.1306 +        val prem = HOLogic.mk_Trueprop (mk_mor UNIVs ctors rec_UNIVs rec_strs id_fs);
  1.1307 +        fun mk_fun_eq f i = HOLogic.mk_eq (f, mk_rec rec_ss i);
  1.1308 +        val unique = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_fun_eq fs ks));
  1.1309 +      in
  1.1310 +        Goal.prove_sorry lthy [] []
  1.1311 +          (fold_rev Logic.all (rec_ss @ fs) (Logic.mk_implies (prem, unique)))
  1.1312 +          (mk_rec_unique_mor_tac rec_defs fst_rec_pair_thms fold_unique_mor_thm)
  1.1313 +          |> Thm.close_derivation
  1.1314 +      end;
  1.1315 +
  1.1316 +    val (ctor_rec_unique_thms, ctor_rec_unique_thm) =
  1.1317 +      `split_conj_thm (split_conj_prems n
  1.1318 +        (mor_UNIV_thm RS iffD2 RS rec_unique_mor_thm)
  1.1319 +        |> Local_Defs.unfold lthy (@{thms convol_o o_id id_o o_assoc[symmetric] fst_convol} @
  1.1320 +           map_id0s @ sym_map_comps) OF replicate n @{thm arg_cong2[of _ _ _ _ convol, OF refl]});
  1.1321 +
  1.1322 +    val timer = time (timer "rec definitions & thms");
  1.1323 +
  1.1324 +    val (ctor_induct_thm, induct_params) =
  1.1325 +      let
  1.1326 +        fun mk_prem phi ctor sets x =
  1.1327 +          let
  1.1328 +            fun mk_IH phi set z =
  1.1329 +              let
  1.1330 +                val prem = HOLogic.mk_Trueprop (HOLogic.mk_mem (z, set $ x));
  1.1331 +                val concl = HOLogic.mk_Trueprop (phi $ z);
  1.1332 +              in
  1.1333 +                Logic.all z (Logic.mk_implies (prem, concl))
  1.1334 +              end;
  1.1335 +
  1.1336 +            val IHs = map3 mk_IH phis (drop m sets) Izs;
  1.1337 +            val concl = HOLogic.mk_Trueprop (phi $ (ctor $ x));
  1.1338 +          in
  1.1339 +            Logic.all x (Logic.list_implies (IHs, concl))
  1.1340 +          end;
  1.1341 +
  1.1342 +        val prems = map4 mk_prem phis ctors FTs_setss xFs;
  1.1343 +
  1.1344 +        fun mk_concl phi z = phi $ z;
  1.1345 +        val concl =
  1.1346 +          HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_concl phis Izs));
  1.1347 +
  1.1348 +        val goal = Logic.list_implies (prems, concl);
  1.1349 +      in
  1.1350 +        (Goal.prove_sorry lthy [] []
  1.1351 +          (fold_rev Logic.all (phis @ Izs) goal)
  1.1352 +          (K (mk_ctor_induct_tac lthy m set_mapss init_induct_thm morE_thms mor_Abs_thm
  1.1353 +            Rep_inverses Abs_inverses Reps))
  1.1354 +        |> Thm.close_derivation,
  1.1355 +        rev (Term.add_tfrees goal []))
  1.1356 +      end;
  1.1357 +
  1.1358 +    val cTs = map (SOME o certifyT lthy o TFree) induct_params;
  1.1359 +
  1.1360 +    val weak_ctor_induct_thms =
  1.1361 +      let fun insts i = (replicate (i - 1) TrueI) @ (asm_rl :: replicate (n - i) TrueI);
  1.1362 +      in map (fn i => (ctor_induct_thm OF insts i) RS mk_conjunctN n i) ks end;
  1.1363 +
  1.1364 +    val (ctor_induct2_thm, induct2_params) =
  1.1365 +      let
  1.1366 +        fun mk_prem phi ctor ctor' sets sets' x y =
  1.1367 +          let
  1.1368 +            fun mk_IH phi set set' z1 z2 =
  1.1369 +              let
  1.1370 +                val prem1 = HOLogic.mk_Trueprop (HOLogic.mk_mem (z1, (set $ x)));
  1.1371 +                val prem2 = HOLogic.mk_Trueprop (HOLogic.mk_mem (z2, (set' $ y)));
  1.1372 +                val concl = HOLogic.mk_Trueprop (phi $ z1 $ z2);
  1.1373 +              in
  1.1374 +                fold_rev Logic.all [z1, z2] (Logic.list_implies ([prem1, prem2], concl))
  1.1375 +              end;
  1.1376 +
  1.1377 +            val IHs = map5 mk_IH phi2s (drop m sets) (drop m sets') Izs1 Izs2;
  1.1378 +            val concl = HOLogic.mk_Trueprop (phi $ (ctor $ x) $ (ctor' $ y));
  1.1379 +          in
  1.1380 +            fold_rev Logic.all [x, y] (Logic.list_implies (IHs, concl))
  1.1381 +          end;
  1.1382 +
  1.1383 +        val prems = map7 mk_prem phi2s ctors ctor's FTs_setss FTs'_setss xFs yFs;
  1.1384 +
  1.1385 +        fun mk_concl phi z1 z2 = phi $ z1 $ z2;
  1.1386 +        val concl = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1.1387 +          (map3 mk_concl phi2s Izs1 Izs2));
  1.1388 +        fun mk_t phi (z1, z1') (z2, z2') =
  1.1389 +          Term.absfree z1' (HOLogic.mk_all (fst z2', snd z2', phi $ z1 $ z2));
  1.1390 +        val cts = map3 (SOME o certify lthy ooo mk_t) phi2s (Izs1 ~~ Izs1') (Izs2 ~~ Izs2');
  1.1391 +        val goal = Logic.list_implies (prems, concl);
  1.1392 +      in
  1.1393 +        (singleton (Proof_Context.export names_lthy lthy)
  1.1394 +          (Goal.prove_sorry lthy [] [] goal
  1.1395 +            (mk_ctor_induct2_tac cTs cts ctor_induct_thm weak_ctor_induct_thms))
  1.1396 +          |> Thm.close_derivation,
  1.1397 +        rev (Term.add_tfrees goal []))
  1.1398 +      end;
  1.1399 +
  1.1400 +    val timer = time (timer "induction");
  1.1401 +
  1.1402 +    fun mk_ctor_map_DEADID_thm ctor_inject map_id0 =
  1.1403 +      trans OF [id_apply, iffD2 OF [ctor_inject, map_id0 RS sym]];
  1.1404 +
  1.1405 +    fun mk_ctor_Irel_DEADID_thm ctor_inject bnf =
  1.1406 +      trans OF [ctor_inject, rel_eq_of_bnf bnf RS @{thm predicate2_eqD} RS sym];
  1.1407 +
  1.1408 +    val IphiTs = map2 mk_pred2T passiveAs passiveBs;
  1.1409 +    val Ipsi1Ts = map2 mk_pred2T passiveAs passiveCs;
  1.1410 +    val Ipsi2Ts = map2 mk_pred2T passiveCs passiveBs;
  1.1411 +    val activephiTs = map2 mk_pred2T activeAs activeBs;
  1.1412 +    val activeIphiTs = map2 mk_pred2T Ts Ts';
  1.1413 +    val (((((Iphis, Ipsi1s), Ipsi2s), activephis), activeIphis), names_lthy) = names_lthy
  1.1414 +      |> mk_Frees "R" IphiTs
  1.1415 +      ||>> mk_Frees "R" Ipsi1Ts
  1.1416 +      ||>> mk_Frees "Q" Ipsi2Ts
  1.1417 +      ||>> mk_Frees "S" activephiTs
  1.1418 +      ||>> mk_Frees "IR" activeIphiTs;
  1.1419 +    val rels = map2 (fn Ds => mk_rel_of_bnf Ds (passiveAs @ Ts) (passiveBs @ Ts')) Dss bnfs;
  1.1420 +
  1.1421 +    (*register new datatypes as BNFs*)
  1.1422 +    val (timer, Ibnfs, (ctor_Imap_o_thms, ctor_Imap_thms), ctor_Iset_thmss',
  1.1423 +        ctor_Irel_thms, Ibnf_notes, lthy) =
  1.1424 +      if m = 0 then
  1.1425 +        (timer, replicate n DEADID_bnf,
  1.1426 +        map_split (`(mk_pointfree lthy)) (map2 mk_ctor_map_DEADID_thm ctor_inject_thms map_ids),
  1.1427 +        replicate n [], map2 mk_ctor_Irel_DEADID_thm ctor_inject_thms bnfs, [], lthy)
  1.1428 +      else let
  1.1429 +        val fTs = map2 (curry op -->) passiveAs passiveBs;
  1.1430 +        val uTs = map2 (curry op -->) Ts Ts';
  1.1431 +
  1.1432 +        val (((((fs, fs'), fs_copy), us), (ys, ys')),
  1.1433 +          names_lthy) = names_lthy
  1.1434 +          |> mk_Frees' "f" fTs
  1.1435 +          ||>> mk_Frees "f" fTs
  1.1436 +          ||>> mk_Frees "u" uTs
  1.1437 +          ||>> mk_Frees' "y" passiveAs;
  1.1438 +
  1.1439 +        val map_FTFT's = map2 (fn Ds =>
  1.1440 +          mk_map_of_bnf Ds (passiveAs @ Ts) (passiveBs @ Ts')) Dss bnfs;
  1.1441 +        fun mk_passive_maps ATs BTs Ts =
  1.1442 +          map2 (fn Ds => mk_map_of_bnf Ds (ATs @ Ts) (BTs @ Ts)) Dss bnfs;
  1.1443 +        fun mk_map_fold_arg fs Ts ctor fmap =
  1.1444 +          HOLogic.mk_comp (ctor, Term.list_comb (fmap, fs @ map HOLogic.id_const Ts));
  1.1445 +        fun mk_map Ts fs Ts' ctors mk_maps =
  1.1446 +          mk_fold Ts (map2 (mk_map_fold_arg fs Ts') ctors (mk_maps Ts'));
  1.1447 +        val pmapsABT' = mk_passive_maps passiveAs passiveBs;
  1.1448 +        val fs_maps = map (mk_map Ts fs Ts' ctor's pmapsABT') ks;
  1.1449 +
  1.1450 +        val ls = 1 upto m;
  1.1451 +        val setsss = map (mk_setss o mk_set_Ts) passiveAs;
  1.1452 +
  1.1453 +        fun mk_col l T z z' sets =
  1.1454 +          let
  1.1455 +            fun mk_UN set = mk_Union T $ (set $ z);
  1.1456 +          in
  1.1457 +            Term.absfree z'
  1.1458 +              (mk_union (nth sets (l - 1) $ z,
  1.1459 +                Library.foldl1 mk_union (map mk_UN (drop m sets))))
  1.1460 +          end;
  1.1461 +
  1.1462 +        val colss = map5 (fn l => fn T => map3 (mk_col l T)) ls passiveAs AFss AFss' setsss;
  1.1463 +        val setss_by_range = map (fn cols => map (mk_fold Ts cols) ks) colss;
  1.1464 +        val setss_by_bnf = transpose setss_by_range;
  1.1465 +
  1.1466 +        val set_bss =
  1.1467 +          map (flat o map2 (fn B => fn b =>
  1.1468 +            if member (op =) resDs (TFree B) then [] else [b]) resBs) set_bss0;
  1.1469 +
  1.1470 +        val ctor_witss =
  1.1471 +          let
  1.1472 +            val witss = map2 (fn Ds => fn bnf => mk_wits_of_bnf
  1.1473 +              (replicate (nwits_of_bnf bnf) Ds)
  1.1474 +              (replicate (nwits_of_bnf bnf) (passiveAs @ Ts)) bnf) Dss bnfs;
  1.1475 +            fun close_wit (I, wit) = fold_rev Term.absfree (map (nth ys') I) wit;
  1.1476 +            fun wit_apply (arg_I, arg_wit) (fun_I, fun_wit) =
  1.1477 +              (union (op =) arg_I fun_I, fun_wit $ arg_wit);
  1.1478 +
  1.1479 +            fun gen_arg support i =
  1.1480 +              if i < m then [([i], nth ys i)]
  1.1481 +              else maps (mk_wit support (nth ctors (i - m)) (i - m)) (nth support (i - m))
  1.1482 +            and mk_wit support ctor i (I, wit) =
  1.1483 +              let val args = map (gen_arg (nth_map i (remove (op =) (I, wit)) support)) I;
  1.1484 +              in
  1.1485 +                (args, [([], wit)])
  1.1486 +                |-> fold (map_product wit_apply)
  1.1487 +                |> map (apsnd (fn t => ctor $ t))
  1.1488 +                |> minimize_wits
  1.1489 +              end;
  1.1490 +          in
  1.1491 +            map3 (fn ctor => fn i => map close_wit o minimize_wits o maps (mk_wit witss ctor i))
  1.1492 +              ctors (0 upto n - 1) witss
  1.1493 +          end;
  1.1494 +
  1.1495 +        val (Ibnf_consts, lthy) =
  1.1496 +          fold_map8 (fn b => fn map_b => fn rel_b => fn set_bs => fn mapx => fn sets => fn wits =>
  1.1497 +              fn T => fn lthy =>
  1.1498 +            define_bnf_consts Dont_Inline (user_policy Note_Some lthy) (SOME deads)
  1.1499 +              map_b rel_b set_bs
  1.1500 +              ((((((b, T), fold_rev Term.absfree fs' mapx), sets), sum_bd), wits), NONE) lthy)
  1.1501 +          bs map_bs rel_bs set_bss fs_maps setss_by_bnf ctor_witss Ts lthy;
  1.1502 +
  1.1503 +        val (_, Iconsts, Iconst_defs, mk_Iconsts) = split_list4 Ibnf_consts;
  1.1504 +        val (_, Isetss, Ibds_Ds, Iwitss_Ds, _) = split_list5 Iconsts;
  1.1505 +        val (Imap_defs, Iset_defss, Ibd_defs, Iwit_defss, Irel_defs) = split_list5 Iconst_defs;
  1.1506 +        val (mk_Imaps_Ds, mk_It_Ds, _, mk_Irels_Ds, _) = split_list5 mk_Iconsts;
  1.1507 +
  1.1508 +        val Irel_unabs_defs = map (fn def => mk_unabs_def m (def RS meta_eq_to_obj_eq)) Irel_defs;
  1.1509 +        val Iset_defs = flat Iset_defss;
  1.1510 +
  1.1511 +        fun mk_Imaps As Bs = map (fn mk => mk deads As Bs) mk_Imaps_Ds;
  1.1512 +        fun mk_Isetss As = map2 (fn mk => fn Isets => map (mk deads As) Isets) mk_It_Ds Isetss;
  1.1513 +        val Ibds = map2 (fn mk => mk deads passiveAs) mk_It_Ds Ibds_Ds;
  1.1514 +        val Iwitss =
  1.1515 +          map2 (fn mk => fn Iwits => map (mk deads passiveAs o snd) Iwits) mk_It_Ds Iwitss_Ds;
  1.1516 +        fun mk_Irels As Bs = map (fn mk => mk deads As Bs) mk_Irels_Ds;
  1.1517 +
  1.1518 +        val Imaps = mk_Imaps passiveAs passiveBs;
  1.1519 +        val fs_Imaps = map (fn m => Term.list_comb (m, fs)) Imaps;
  1.1520 +        val fs_copy_Imaps = map (fn m => Term.list_comb (m, fs_copy)) Imaps;
  1.1521 +        val (Isetss_by_range, Isetss_by_bnf) = `transpose (mk_Isetss passiveAs);
  1.1522 +
  1.1523 +        val map_setss = map (fn T => map2 (fn Ds =>
  1.1524 +          mk_map_of_bnf Ds (passiveAs @ Ts) (mk_set_Ts T)) Dss bnfs) passiveAs;
  1.1525 +
  1.1526 +        val timer = time (timer "bnf constants for the new datatypes");
  1.1527 +
  1.1528 +        val (ctor_Imap_thms, ctor_Imap_o_thms) =
  1.1529 +          let
  1.1530 +            fun mk_goal fs_map map ctor ctor' = fold_rev Logic.all fs
  1.1531 +              (mk_Trueprop_eq (HOLogic.mk_comp (fs_map, ctor),
  1.1532 +                HOLogic.mk_comp (ctor', Term.list_comb (map, fs @ fs_Imaps))));
  1.1533 +            val goals = map4 mk_goal fs_Imaps map_FTFT's ctors ctor's;
  1.1534 +            val maps =
  1.1535 +              map4 (fn goal => fn foldx => fn map_comp_id => fn map_cong0 =>
  1.1536 +                Goal.prove_sorry lthy [] [] goal
  1.1537 +                  (fn {context = ctxt, prems = _} => unfold_thms_tac ctxt Imap_defs THEN
  1.1538 +                    mk_map_tac m n foldx map_comp_id map_cong0)
  1.1539 +                |> Thm.close_derivation)
  1.1540 +              goals ctor_fold_thms map_comp_id_thms map_cong0s;
  1.1541 +          in
  1.1542 +            `(map (fn thm => thm RS @{thm comp_eq_dest})) maps
  1.1543 +          end;
  1.1544 +
  1.1545 +        val (ctor_Imap_unique_thms, ctor_Imap_unique_thm) =
  1.1546 +          let
  1.1547 +            fun mk_prem u map ctor ctor' =
  1.1548 +              mk_Trueprop_eq (HOLogic.mk_comp (u, ctor),
  1.1549 +                HOLogic.mk_comp (ctor', Term.list_comb (map, fs @ us)));
  1.1550 +            val prems = map4 mk_prem us map_FTFT's ctors ctor's;
  1.1551 +            val goal =
  1.1552 +              HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1.1553 +                (map2 (curry HOLogic.mk_eq) us fs_Imaps));
  1.1554 +            val unique = Goal.prove_sorry lthy [] []
  1.1555 +              (fold_rev Logic.all (us @ fs) (Logic.list_implies (prems, goal)))
  1.1556 +              (fn {context = ctxt, prems = _} => unfold_thms_tac ctxt Imap_defs THEN
  1.1557 +                mk_ctor_map_unique_tac ctor_fold_unique_thm sym_map_comps ctxt)
  1.1558 +              |> Thm.close_derivation;
  1.1559 +          in
  1.1560 +            `split_conj_thm unique
  1.1561 +          end;
  1.1562 +
  1.1563 +        val timer = time (timer "map functions for the new datatypes");
  1.1564 +
  1.1565 +        val ctor_Iset_thmss =
  1.1566 +          let
  1.1567 +            fun mk_goal sets ctor set col map =
  1.1568 +              mk_Trueprop_eq (HOLogic.mk_comp (set, ctor),
  1.1569 +                HOLogic.mk_comp (col, Term.list_comb (map, passive_ids @ sets)));
  1.1570 +            val goalss =
  1.1571 +              map3 (fn sets => map4 (mk_goal sets) ctors sets) Isetss_by_range colss map_setss;
  1.1572 +            val setss = map (map2 (fn foldx => fn goal =>
  1.1573 +                Goal.prove_sorry lthy [] [] goal (fn {context = ctxt, prems = _} =>
  1.1574 +                  unfold_thms_tac ctxt Iset_defs THEN mk_set_tac foldx)
  1.1575 +                |> Thm.close_derivation)
  1.1576 +              ctor_fold_thms) goalss;
  1.1577 +
  1.1578 +            fun mk_simp_goal pas_set act_sets sets ctor z set =
  1.1579 +              Logic.all z (mk_Trueprop_eq (set $ (ctor $ z),
  1.1580 +                mk_union (pas_set $ z,
  1.1581 +                  Library.foldl1 mk_union (map2 (fn X => mk_UNION (X $ z)) act_sets sets))));
  1.1582 +            val simp_goalss =
  1.1583 +              map2 (fn i => fn sets =>
  1.1584 +                map4 (fn Fsets => mk_simp_goal (nth Fsets (i - 1)) (drop m Fsets) sets)
  1.1585 +                  FTs_setss ctors xFs sets)
  1.1586 +                ls Isetss_by_range;
  1.1587 +
  1.1588 +            val ctor_setss = map3 (fn i => map3 (fn set_nats => fn goal => fn set =>
  1.1589 +                Goal.prove_sorry lthy [] [] goal
  1.1590 +                  (K (mk_ctor_set_tac set (nth set_nats (i - 1)) (drop m set_nats)))
  1.1591 +                |> Thm.close_derivation)
  1.1592 +              set_mapss) ls simp_goalss setss;
  1.1593 +          in
  1.1594 +            ctor_setss
  1.1595 +          end;
  1.1596 +
  1.1597 +        fun mk_set_thms ctor_set = (@{thm xt1(3)} OF [ctor_set, @{thm Un_upper1}]) ::
  1.1598 +          map (fn i => (@{thm xt1(3)} OF [ctor_set, @{thm Un_upper2}]) RS
  1.1599 +            (mk_Un_upper n i RS subset_trans) RSN
  1.1600 +            (2, @{thm UN_upper} RS subset_trans))
  1.1601 +            (1 upto n);
  1.1602 +        val set_Iset_thmsss = transpose (map (map mk_set_thms) ctor_Iset_thmss);
  1.1603 +
  1.1604 +        val timer = time (timer "set functions for the new datatypes");
  1.1605 +
  1.1606 +        val cxs = map (SOME o certify lthy) Izs;
  1.1607 +        val Isetss_by_range' =
  1.1608 +          map (map (Term.subst_atomic_types (passiveAs ~~ passiveBs))) Isetss_by_range;
  1.1609 +
  1.1610 +        val Iset_Imap0_thmss =
  1.1611 +          let
  1.1612 +            fun mk_set_map0 f map z set set' =
  1.1613 +              HOLogic.mk_eq (mk_image f $ (set $ z), set' $ (map $ z));
  1.1614 +
  1.1615 +            fun mk_cphi f map z set set' = certify lthy
  1.1616 +              (Term.absfree (dest_Free z) (mk_set_map0 f map z set set'));
  1.1617 +
  1.1618 +            val csetss = map (map (certify lthy)) Isetss_by_range';
  1.1619 +
  1.1620 +            val cphiss = map3 (fn f => fn sets => fn sets' =>
  1.1621 +              (map4 (mk_cphi f) fs_Imaps Izs sets sets')) fs Isetss_by_range Isetss_by_range';
  1.1622 +
  1.1623 +            val inducts = map (fn cphis =>
  1.1624 +              Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm) cphiss;
  1.1625 +
  1.1626 +            val goals =
  1.1627 +              map3 (fn f => fn sets => fn sets' =>
  1.1628 +                HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1.1629 +                  (map4 (mk_set_map0 f) fs_Imaps Izs sets sets')))
  1.1630 +                  fs Isetss_by_range Isetss_by_range';
  1.1631 +
  1.1632 +            fun mk_tac induct = mk_set_nat_tac m (rtac induct) set_mapss ctor_Imap_thms;
  1.1633 +            val thms =
  1.1634 +              map5 (fn goal => fn csets => fn ctor_sets => fn induct => fn i =>
  1.1635 +                singleton (Proof_Context.export names_lthy lthy)
  1.1636 +                  (Goal.prove_sorry lthy [] [] goal (mk_tac induct csets ctor_sets i))
  1.1637 +                |> Thm.close_derivation)
  1.1638 +              goals csetss ctor_Iset_thmss inducts ls;
  1.1639 +          in
  1.1640 +            map split_conj_thm thms
  1.1641 +          end;
  1.1642 +
  1.1643 +        val Iset_bd_thmss =
  1.1644 +          let
  1.1645 +            fun mk_set_bd z bd set = mk_ordLeq (mk_card_of (set $ z)) bd;
  1.1646 +
  1.1647 +            fun mk_cphi z set = certify lthy (Term.absfree (dest_Free z) (mk_set_bd z sum_bd set));
  1.1648 +
  1.1649 +            val cphiss = map (map2 mk_cphi Izs) Isetss_by_range;
  1.1650 +
  1.1651 +            val inducts = map (fn cphis =>
  1.1652 +              Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm) cphiss;
  1.1653 +
  1.1654 +            val goals =
  1.1655 +              map (fn sets =>
  1.1656 +                HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1.1657 +                  (map3 mk_set_bd Izs Ibds sets))) Isetss_by_range;
  1.1658 +
  1.1659 +            fun mk_tac induct = mk_set_bd_tac m (rtac induct) sum_Cinfinite set_bd_sumss;
  1.1660 +            val thms =
  1.1661 +              map4 (fn goal => fn ctor_sets => fn induct => fn i =>
  1.1662 +                singleton (Proof_Context.export names_lthy lthy)
  1.1663 +                  (Goal.prove_sorry lthy [] [] goal
  1.1664 +                    (fn {context = ctxt, prems = _} => unfold_thms_tac ctxt Ibd_defs THEN
  1.1665 +                      mk_tac induct ctor_sets i ctxt))
  1.1666 +                |> Thm.close_derivation)
  1.1667 +              goals ctor_Iset_thmss inducts ls;
  1.1668 +          in
  1.1669 +            map split_conj_thm thms
  1.1670 +          end;
  1.1671 +
  1.1672 +        val Imap_cong0_thms =
  1.1673 +          let
  1.1674 +            fun mk_prem z set f g y y' =
  1.1675 +              mk_Ball (set $ z) (Term.absfree y' (HOLogic.mk_eq (f $ y, g $ y)));
  1.1676 +
  1.1677 +            fun mk_map_cong0 sets z fmap gmap =
  1.1678 +              HOLogic.mk_imp
  1.1679 +                (Library.foldr1 HOLogic.mk_conj (map5 (mk_prem z) sets fs fs_copy ys ys'),
  1.1680 +                HOLogic.mk_eq (fmap $ z, gmap $ z));
  1.1681 +
  1.1682 +            fun mk_cphi sets z fmap gmap =
  1.1683 +              certify lthy (Term.absfree (dest_Free z) (mk_map_cong0 sets z fmap gmap));
  1.1684 +
  1.1685 +            val cphis = map4 mk_cphi Isetss_by_bnf Izs fs_Imaps fs_copy_Imaps;
  1.1686 +
  1.1687 +            val induct = Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm;
  1.1688 +
  1.1689 +            val goal =
  1.1690 +              HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1.1691 +                (map4 mk_map_cong0 Isetss_by_bnf Izs fs_Imaps fs_copy_Imaps));
  1.1692 +
  1.1693 +            val thm = singleton (Proof_Context.export names_lthy lthy)
  1.1694 +              (Goal.prove_sorry lthy [] [] goal
  1.1695 +              (mk_mcong_tac (rtac induct) set_Iset_thmsss map_cong0s ctor_Imap_thms))
  1.1696 +              |> Thm.close_derivation;
  1.1697 +          in
  1.1698 +            split_conj_thm thm
  1.1699 +          end;
  1.1700 +
  1.1701 +        val in_rels = map in_rel_of_bnf bnfs;
  1.1702 +        val in_Irels = map (fn def => trans OF [def, @{thm OO_Grp_alt}] RS @{thm predicate2_eqD})
  1.1703 +            Irel_unabs_defs;
  1.1704 +
  1.1705 +        val ctor_Iset_incl_thmss = map (map hd) set_Iset_thmsss;
  1.1706 +        val ctor_set_Iset_incl_thmsss = map (transpose o map tl) set_Iset_thmsss;
  1.1707 +        val ctor_Iset_thmss' = transpose ctor_Iset_thmss;
  1.1708 +
  1.1709 +        val Irels = mk_Irels passiveAs passiveBs;
  1.1710 +        val Irelphis = map (fn rel => Term.list_comb (rel, Iphis)) Irels;
  1.1711 +        val relphis = map (fn rel => Term.list_comb (rel, Iphis @ Irelphis)) rels;
  1.1712 +        val Irelpsi1s = map (fn rel => Term.list_comb (rel, Ipsi1s)) (mk_Irels passiveAs passiveCs);
  1.1713 +        val Irelpsi2s = map (fn rel => Term.list_comb (rel, Ipsi2s)) (mk_Irels passiveCs passiveBs);
  1.1714 +        val Irelpsi12s = map (fn rel =>
  1.1715 +            Term.list_comb (rel, map2 (curry mk_rel_compp) Ipsi1s Ipsi2s)) Irels;
  1.1716 +
  1.1717 +        val ctor_Irel_thms =
  1.1718 +          let
  1.1719 +            fun mk_goal xF yF ctor ctor' Irelphi relphi = fold_rev Logic.all (xF :: yF :: Iphis)
  1.1720 +              (mk_Trueprop_eq (Irelphi $ (ctor $ xF) $ (ctor' $ yF), relphi $ xF $ yF));
  1.1721 +            val goals = map6 mk_goal xFs yFs ctors ctor's Irelphis relphis;
  1.1722 +          in
  1.1723 +            map12 (fn i => fn goal => fn in_rel => fn map_comp0 => fn map_cong0 =>
  1.1724 +              fn ctor_map => fn ctor_sets => fn ctor_inject => fn ctor_dtor =>
  1.1725 +              fn set_map0s => fn ctor_set_incls => fn ctor_set_set_inclss =>
  1.1726 +              Goal.prove_sorry lthy [] [] goal
  1.1727 +               (K (mk_ctor_rel_tac lthy in_Irels i in_rel map_comp0 map_cong0 ctor_map ctor_sets
  1.1728 +                 ctor_inject ctor_dtor set_map0s ctor_set_incls ctor_set_set_inclss))
  1.1729 +              |> Thm.close_derivation)
  1.1730 +            ks goals in_rels map_comps map_cong0s ctor_Imap_thms ctor_Iset_thmss'
  1.1731 +              ctor_inject_thms ctor_dtor_thms set_mapss ctor_Iset_incl_thmss
  1.1732 +              ctor_set_Iset_incl_thmsss
  1.1733 +          end;
  1.1734 +
  1.1735 +        val le_Irel_OO_thm =
  1.1736 +          let
  1.1737 +            fun mk_le_Irel_OO Irelpsi1 Irelpsi2 Irelpsi12 Iz1 Iz2 =
  1.1738 +              HOLogic.mk_imp (mk_rel_compp (Irelpsi1, Irelpsi2) $ Iz1 $ Iz2,
  1.1739 +                Irelpsi12 $ Iz1 $ Iz2);
  1.1740 +            val goals = map5 mk_le_Irel_OO Irelpsi1s Irelpsi2s Irelpsi12s Izs1 Izs2;
  1.1741 +
  1.1742 +            val cTs = map (SOME o certifyT lthy o TFree) induct2_params;
  1.1743 +            val cxs = map (SOME o certify lthy) (splice Izs1 Izs2);
  1.1744 +            fun mk_cphi z1 z2 goal = SOME (certify lthy (Term.absfree z1 (Term.absfree z2 goal)));
  1.1745 +            val cphis = map3 mk_cphi Izs1' Izs2' goals;
  1.1746 +            val induct = Drule.instantiate' cTs (cphis @ cxs) ctor_induct2_thm;
  1.1747 +
  1.1748 +            val goal = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj goals);
  1.1749 +          in
  1.1750 +            singleton (Proof_Context.export names_lthy lthy)
  1.1751 +              (Goal.prove_sorry lthy [] [] goal
  1.1752 +                (mk_le_rel_OO_tac m induct ctor_nchotomy_thms ctor_Irel_thms rel_mono_strongs
  1.1753 +                  rel_OOs))
  1.1754 +              |> Thm.close_derivation
  1.1755 +          end;
  1.1756 +
  1.1757 +        val timer = time (timer "helpers for BNF properties");
  1.1758 +
  1.1759 +        val map_id0_tacs = map (K o mk_map_id0_tac map_id0s) ctor_Imap_unique_thms;
  1.1760 +        val map_comp0_tacs =
  1.1761 +          map2 (K oo mk_map_comp0_tac map_comps ctor_Imap_thms) ctor_Imap_unique_thms ks;
  1.1762 +        val map_cong0_tacs = map (mk_map_cong0_tac m) Imap_cong0_thms;
  1.1763 +        val set_map0_tacss = map (map (K o mk_set_map0_tac)) (transpose Iset_Imap0_thmss);
  1.1764 +        val bd_co_tacs = replicate n (fn {context = ctxt, prems = _} =>
  1.1765 +          unfold_thms_tac ctxt Ibd_defs THEN mk_bd_card_order_tac bd_card_orders);
  1.1766 +        val bd_cinf_tacs = replicate n (fn {context = ctxt, prems = _} =>
  1.1767 +          unfold_thms_tac ctxt Ibd_defs THEN rtac (sum_Cinfinite RS conjunct1) 1);
  1.1768 +        val set_bd_tacss = map (map (fn thm => K (rtac thm 1))) (transpose Iset_bd_thmss);
  1.1769 +        val le_rel_OO_tacs = map (fn i =>
  1.1770 +          K ((rtac @{thm predicate2I} THEN' etac (le_Irel_OO_thm RS mk_conjunctN n i RS mp)) 1)) ks;
  1.1771 +
  1.1772 +        val rel_OO_Grp_tacs = map (fn def => K (rtac def 1)) Irel_unabs_defs;
  1.1773 +
  1.1774 +        val tacss = map9 zip_axioms map_id0_tacs map_comp0_tacs map_cong0_tacs set_map0_tacss
  1.1775 +          bd_co_tacs bd_cinf_tacs set_bd_tacss le_rel_OO_tacs rel_OO_Grp_tacs;
  1.1776 +
  1.1777 +        fun wit_tac {context = ctxt, prems = _} = unfold_thms_tac ctxt (flat Iwit_defss) THEN
  1.1778 +          mk_wit_tac ctxt n (flat ctor_Iset_thmss) (maps wit_thms_of_bnf bnfs);
  1.1779 +
  1.1780 +        val (Ibnfs, lthy) =
  1.1781 +          fold_map5 (fn tacs => fn map_b => fn rel_b => fn set_bs => fn consts => fn lthy =>
  1.1782 +            bnf_def Do_Inline (user_policy Note_Some) I tacs wit_tac (SOME deads)
  1.1783 +              map_b rel_b set_bs consts lthy
  1.1784 +            |> register_bnf (Local_Theory.full_name lthy b))
  1.1785 +          tacss map_bs rel_bs set_bss
  1.1786 +            ((((((bs ~~ Ts) ~~ Imaps) ~~ Isetss_by_bnf) ~~ Ibds) ~~ Iwitss) ~~ map SOME Irels)
  1.1787 +            lthy;
  1.1788 +
  1.1789 +        val timer = time (timer "registered new datatypes as BNFs");
  1.1790 +
  1.1791 +        val ls' = if m = 1 then [0] else ls
  1.1792 +
  1.1793 +        val Ibnf_common_notes =
  1.1794 +          [(ctor_map_uniqueN, [ctor_Imap_unique_thm])]
  1.1795 +          |> map (fn (thmN, thms) =>
  1.1796 +            ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]));
  1.1797 +
  1.1798 +        val Ibnf_notes =
  1.1799 +          [(ctor_mapN, map single ctor_Imap_thms),
  1.1800 +          (ctor_relN, map single ctor_Irel_thms),
  1.1801 +          (ctor_set_inclN, ctor_Iset_incl_thmss),
  1.1802 +          (ctor_set_set_inclN, map flat ctor_set_Iset_incl_thmsss)] @
  1.1803 +          map2 (fn i => fn thms => (mk_ctor_setN i, map single thms)) ls' ctor_Iset_thmss
  1.1804 +          |> maps (fn (thmN, thmss) =>
  1.1805 +            map2 (fn b => fn thms =>
  1.1806 +              ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]))
  1.1807 +            bs thmss)
  1.1808 +      in
  1.1809 +        (timer, Ibnfs, (ctor_Imap_o_thms, ctor_Imap_thms), ctor_Iset_thmss',
  1.1810 +          ctor_Irel_thms, Ibnf_common_notes @ Ibnf_notes, lthy)
  1.1811 +      end;
  1.1812 +
  1.1813 +      val ctor_fold_o_Imap_thms = mk_xtor_un_fold_o_map_thms Least_FP false m ctor_fold_unique_thm
  1.1814 +        ctor_Imap_o_thms (map (mk_pointfree lthy) ctor_fold_thms) sym_map_comps map_cong0s;
  1.1815 +      val ctor_rec_o_Imap_thms = mk_xtor_un_fold_o_map_thms Least_FP true m ctor_rec_unique_thm
  1.1816 +        ctor_Imap_o_thms (map (mk_pointfree lthy) ctor_rec_thms) sym_map_comps map_cong0s;
  1.1817 +
  1.1818 +      val Irels = if m = 0 then map HOLogic.eq_const Ts
  1.1819 +        else map (mk_rel_of_bnf deads passiveAs passiveBs) Ibnfs;
  1.1820 +      val Irel_induct_thm =
  1.1821 +        mk_rel_xtor_co_induct_thm Least_FP rels activeIphis Irels Iphis xFs yFs ctors ctor's
  1.1822 +          (mk_rel_induct_tac m ctor_induct2_thm ks ctor_Irel_thms rel_mono_strongs) lthy;
  1.1823 +
  1.1824 +      val rels = map2 (fn Ds => mk_rel_of_bnf Ds allAs allBs') Dss bnfs;
  1.1825 +      val ctor_fold_transfer_thms =
  1.1826 +        mk_un_fold_transfer_thms Least_FP rels activephis Irels Iphis
  1.1827 +          (mk_folds passiveAs activeAs) (mk_folds passiveBs activeBs)
  1.1828 +          (mk_fold_transfer_tac m Irel_induct_thm (map map_transfer_of_bnf bnfs) ctor_fold_thms)
  1.1829 +          lthy;
  1.1830 +
  1.1831 +      val timer = time (timer "relator induction");
  1.1832 +
  1.1833 +      val common_notes =
  1.1834 +        [(ctor_inductN, [ctor_induct_thm]),
  1.1835 +        (ctor_induct2N, [ctor_induct2_thm]),
  1.1836 +        (rel_inductN, [Irel_induct_thm]),
  1.1837 +        (ctor_fold_transferN, ctor_fold_transfer_thms)]
  1.1838 +        |> map (fn (thmN, thms) =>
  1.1839 +          ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]));
  1.1840 +
  1.1841 +      val notes =
  1.1842 +        [(ctor_dtorN, ctor_dtor_thms),
  1.1843 +        (ctor_exhaustN, ctor_exhaust_thms),
  1.1844 +        (ctor_foldN, ctor_fold_thms),
  1.1845 +        (ctor_fold_uniqueN, ctor_fold_unique_thms),
  1.1846 +        (ctor_rec_uniqueN, ctor_rec_unique_thms),
  1.1847 +        (ctor_fold_o_mapN, ctor_fold_o_Imap_thms),
  1.1848 +        (ctor_rec_o_mapN, ctor_rec_o_Imap_thms),
  1.1849 +        (ctor_injectN, ctor_inject_thms),
  1.1850 +        (ctor_recN, ctor_rec_thms),
  1.1851 +        (dtor_ctorN, dtor_ctor_thms),
  1.1852 +        (dtor_exhaustN, dtor_exhaust_thms),
  1.1853 +        (dtor_injectN, dtor_inject_thms)]
  1.1854 +        |> map (apsnd (map single))
  1.1855 +        |> maps (fn (thmN, thmss) =>
  1.1856 +          map2 (fn b => fn thms =>
  1.1857 +            ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]))
  1.1858 +          bs thmss);
  1.1859 +
  1.1860 +    (*FIXME: once the package exports all the necessary high-level characteristic theorems,
  1.1861 +       those should not only be concealed but rather not noted at all*)
  1.1862 +    val maybe_conceal_notes = note_all = false ? map (apfst (apfst Binding.conceal));
  1.1863 +  in
  1.1864 +    timer;
  1.1865 +    ({Ts = Ts, bnfs = Ibnfs, ctors = ctors, dtors = dtors, xtor_co_iterss = transpose [folds, recs],
  1.1866 +      xtor_co_induct = ctor_induct_thm, dtor_ctors = dtor_ctor_thms, ctor_dtors = ctor_dtor_thms,
  1.1867 +      ctor_injects = ctor_inject_thms, dtor_injects = dtor_inject_thms,
  1.1868 +      xtor_map_thms = ctor_Imap_thms, xtor_set_thmss = ctor_Iset_thmss',
  1.1869 +      xtor_rel_thms = ctor_Irel_thms,
  1.1870 +      xtor_co_iter_thmss = transpose [ctor_fold_thms, ctor_rec_thms],
  1.1871 +      xtor_co_iter_o_map_thmss = transpose [ctor_fold_o_Imap_thms, ctor_rec_o_Imap_thms],
  1.1872 +      rel_xtor_co_induct_thm = Irel_induct_thm},
  1.1873 +     lthy |> Local_Theory.notes (maybe_conceal_notes (common_notes @ notes @ Ibnf_notes)) |> snd)
  1.1874 +  end;
  1.1875 +
  1.1876 +val _ =
  1.1877 +  Outer_Syntax.local_theory @{command_spec "datatype_new"} "define new-style inductive datatypes"
  1.1878 +    (parse_co_datatype_cmd Least_FP construct_lfp);
  1.1879 +
  1.1880 +val _ = Outer_Syntax.local_theory @{command_spec "primrec_new"}
  1.1881 +  "define primitive recursive functions"
  1.1882 +  (Parse.fixes -- Parse_Spec.where_alt_specs >> (snd oo uncurry add_primrec_cmd));
  1.1883 +
  1.1884 +end;