src/HOL/BNF/Tools/bnf_lfp.ML
author blanchet
Mon May 06 21:20:54 2013 +0200 (2013-05-06)
changeset 51884 2928fda12661
parent 51869 d58cd7673b04
child 51893 596baae88a88
permissions -rw-r--r--
factor out construction of iterator
     1 (*  Title:      HOL/BNF/Tools/bnf_lfp.ML
     2     Author:     Dmitriy Traytel, TU Muenchen
     3     Author:     Andrei Popescu, TU Muenchen
     4     Copyright   2012
     5 
     6 Datatype construction.
     7 *)
     8 
     9 signature BNF_LFP =
    10 sig
    11   val construct_lfp: mixfix list -> binding list -> binding list -> binding list list ->
    12     binding list -> (string * sort) list -> typ list * typ list list -> BNF_Def.bnf list ->
    13     local_theory -> BNF_FP_Util.fp_result * local_theory
    14 end;
    15 
    16 structure BNF_LFP : BNF_LFP =
    17 struct
    18 
    19 open BNF_Def
    20 open BNF_Util
    21 open BNF_Tactics
    22 open BNF_Comp
    23 open BNF_FP_Util
    24 open BNF_FP_Def_Sugar
    25 open BNF_LFP_Util
    26 open BNF_LFP_Tactics
    27 
    28 (*all BNFs have the same lives*)
    29 fun construct_lfp mixfixes map_bs rel_bs set_bss bs resBs (resDs, Dss) bnfs lthy =
    30   let
    31     val timer = time (Timer.startRealTimer ());
    32 
    33     val note_all = Config.get lthy bnf_note_all;
    34 
    35     val live = live_of_bnf (hd bnfs);
    36     val n = length bnfs; (*active*)
    37     val ks = 1 upto n;
    38     val m = live - n; (*passive, if 0 don't generate a new BNF*)
    39     val b = Binding.name (mk_common_name (map Binding.name_of bs));
    40 
    41     (* TODO: check if m, n, etc., are sane *)
    42 
    43     val deads = fold (union (op =)) Dss resDs;
    44     val names_lthy = fold Variable.declare_typ deads lthy;
    45 
    46     (* tvars *)
    47     val (((((((passiveAs, activeAs), allAs)), (passiveBs, activeBs)),
    48       activeCs), passiveXs), passiveYs) = names_lthy
    49       |> mk_TFrees live
    50       |> apfst (`(chop m))
    51       ||> mk_TFrees live
    52       ||>> apfst (chop m)
    53       ||>> mk_TFrees n
    54       ||>> mk_TFrees m
    55       ||> fst o mk_TFrees m;
    56 
    57     val Ass = replicate n allAs;
    58     val allBs = passiveAs @ activeBs;
    59     val Bss = replicate n allBs;
    60     val allCs = passiveAs @ activeCs;
    61     val allCs' = passiveBs @ activeCs;
    62     val Css' = replicate n allCs';
    63 
    64     (* types *)
    65     val dead_poss =
    66       map (fn T => if member (op =) deads (TFree T) then SOME (TFree T) else NONE) resBs;
    67     fun mk_param NONE passive = (hd passive, tl passive)
    68       | mk_param (SOME a) passive = (a, passive);
    69     val mk_params = fold_map mk_param dead_poss #> fst;
    70 
    71     fun mk_FTs Ts = map2 (fn Ds => mk_T_of_bnf Ds Ts) Dss bnfs;
    72     val (params, params') = `(map Term.dest_TFree) (mk_params passiveAs);
    73     val FTsAs = mk_FTs allAs;
    74     val FTsBs = mk_FTs allBs;
    75     val FTsCs = mk_FTs allCs;
    76     val ATs = map HOLogic.mk_setT passiveAs;
    77     val BTs = map HOLogic.mk_setT activeAs;
    78     val B'Ts = map HOLogic.mk_setT activeBs;
    79     val B''Ts = map HOLogic.mk_setT activeCs;
    80     val sTs = map2 (curry (op -->)) FTsAs activeAs;
    81     val s'Ts = map2 (curry (op -->)) FTsBs activeBs;
    82     val s''Ts = map2 (curry (op -->)) FTsCs activeCs;
    83     val fTs = map2 (curry (op -->)) activeAs activeBs;
    84     val inv_fTs = map2 (curry (op -->)) activeBs activeAs;
    85     val self_fTs = map2 (curry (op -->)) activeAs activeAs;
    86     val gTs = map2 (curry (op -->)) activeBs activeCs;
    87     val all_gTs = map2 (curry (op -->)) allBs allCs';
    88     val prodBsAs = map2 (curry HOLogic.mk_prodT) activeBs activeAs;
    89     val prodFTs = mk_FTs (passiveAs @ prodBsAs);
    90     val prod_sTs = map2 (curry (op -->)) prodFTs activeAs;
    91 
    92     (* terms *)
    93     val mapsAsAs = map4 mk_map_of_bnf Dss Ass Ass bnfs;
    94     val mapsAsBs = map4 mk_map_of_bnf Dss Ass Bss bnfs;
    95     val mapsBsAs = map4 mk_map_of_bnf Dss Bss Ass bnfs;
    96     val mapsBsCs' = map4 mk_map_of_bnf Dss Bss Css' bnfs;
    97     val mapsAsCs' = map4 mk_map_of_bnf Dss Ass Css' bnfs;
    98     val map_fsts = map4 mk_map_of_bnf Dss (replicate n (passiveAs @ prodBsAs)) Bss bnfs;
    99     val map_fsts_rev = map4 mk_map_of_bnf Dss Bss (replicate n (passiveAs @ prodBsAs)) bnfs;
   100     fun mk_setss Ts = map3 mk_sets_of_bnf (map (replicate live) Dss)
   101       (map (replicate live) (replicate n Ts)) bnfs;
   102     val setssAs = mk_setss allAs;
   103     val bds = map3 mk_bd_of_bnf Dss Ass bnfs;
   104     val witss = map wits_of_bnf bnfs;
   105 
   106     val (((((((((((((((((((zs, zs'), As), Bs), Bs_copy), B's), B''s), ss), prod_ss), s's), s''s),
   107       fs), fs_copy), inv_fs), self_fs), gs), all_gs), (xFs, xFs')), (yFs, yFs')),
   108       names_lthy) = lthy
   109       |> mk_Frees' "z" activeAs
   110       ||>> mk_Frees "A" ATs
   111       ||>> mk_Frees "B" BTs
   112       ||>> mk_Frees "B" BTs
   113       ||>> mk_Frees "B'" B'Ts
   114       ||>> mk_Frees "B''" B''Ts
   115       ||>> mk_Frees "s" sTs
   116       ||>> mk_Frees "prods" prod_sTs
   117       ||>> mk_Frees "s'" s'Ts
   118       ||>> mk_Frees "s''" s''Ts
   119       ||>> mk_Frees "f" fTs
   120       ||>> mk_Frees "f" fTs
   121       ||>> mk_Frees "f" inv_fTs
   122       ||>> mk_Frees "f" self_fTs
   123       ||>> mk_Frees "g" gTs
   124       ||>> mk_Frees "g" all_gTs
   125       ||>> mk_Frees' "x" FTsAs
   126       ||>> mk_Frees' "y" FTsBs;
   127 
   128     val passive_UNIVs = map HOLogic.mk_UNIV passiveAs;
   129     val active_UNIVs = map HOLogic.mk_UNIV activeAs;
   130     val prod_UNIVs = map HOLogic.mk_UNIV prodBsAs;
   131     val passive_ids = map HOLogic.id_const passiveAs;
   132     val active_ids = map HOLogic.id_const activeAs;
   133     val fsts = map fst_const prodBsAs;
   134 
   135     (* thms *)
   136     val bd_card_orders = map bd_card_order_of_bnf bnfs;
   137     val bd_Card_orders = map bd_Card_order_of_bnf bnfs;
   138     val bd_Card_order = hd bd_Card_orders;
   139     val bd_Cinfinite = bd_Cinfinite_of_bnf (hd bnfs);
   140     val bd_Cnotzeros = map bd_Cnotzero_of_bnf bnfs;
   141     val bd_Cnotzero = hd bd_Cnotzeros;
   142     val in_bds = map in_bd_of_bnf bnfs;
   143     val sym_map_comps = map (fn bnf => map_comp_of_bnf bnf RS sym) bnfs;
   144     val map_comp's = map map_comp'_of_bnf bnfs;
   145     val map_cong0s = map map_cong0_of_bnf bnfs;
   146     val map_ids = map map_id_of_bnf bnfs;
   147     val map_id's = map map_id'_of_bnf bnfs;
   148     val map_wpulls = map map_wpull_of_bnf bnfs;
   149     val set_bdss = map set_bd_of_bnf bnfs;
   150     val set_map'ss = map set_map'_of_bnf bnfs;
   151 
   152     val timer = time (timer "Extracted terms & thms");
   153 
   154     (* nonemptiness check *)
   155     fun new_wit X (wit: nonemptiness_witness) = subset (op =) (#I wit, (0 upto m - 1) @ map snd X);
   156 
   157     val all = m upto m + n - 1;
   158 
   159     fun enrich X = map_filter (fn i =>
   160       (case find_first (fn (_, i') => i = i') X of
   161         NONE =>
   162           (case find_index (new_wit X) (nth witss (i - m)) of
   163             ~1 => NONE
   164           | j => SOME (j, i))
   165       | SOME ji => SOME ji)) all;
   166     val reachable = fixpoint (op =) enrich [];
   167     val _ = (case subtract (op =) (map snd reachable) all of
   168         [] => ()
   169       | i :: _ => error ("Cannot define empty datatype " ^ quote (Binding.name_of (nth bs (i - m)))));
   170 
   171     val wit_thms = flat (map2 (fn bnf => fn (j, _) => nth (wit_thmss_of_bnf bnf) j) bnfs reachable);
   172 
   173     val timer = time (timer "Checked nonemptiness");
   174 
   175     (* derived thms *)
   176 
   177     (*map g1 ... gm g(m+1) ... g(m+n) (map id ... id f(m+1) ... f(m+n) x)=
   178       map g1 ... gm (g(m+1) o f(m+1)) ... (g(m+n) o f(m+n)) x*)
   179     fun mk_map_comp_id x mapAsBs mapBsCs mapAsCs map_comp =
   180       let
   181         val lhs = Term.list_comb (mapBsCs, all_gs) $
   182           (Term.list_comb (mapAsBs, passive_ids @ fs) $ x);
   183         val rhs = Term.list_comb (mapAsCs,
   184           take m all_gs @ map HOLogic.mk_comp (drop m all_gs ~~ fs)) $ x;
   185       in
   186         Goal.prove_sorry lthy [] []
   187           (fold_rev Logic.all (x :: fs @ all_gs) (mk_Trueprop_eq (lhs, rhs)))
   188           (K (mk_map_comp_id_tac map_comp))
   189         |> Thm.close_derivation
   190       end;
   191 
   192     val map_comp_id_thms = map5 mk_map_comp_id xFs mapsAsBs mapsBsCs' mapsAsCs' map_comp's;
   193 
   194     (*forall a : set(m+1) x. f(m+1) a = a; ...; forall a : set(m+n) x. f(m+n) a = a ==>
   195       map id ... id f(m+1) ... f(m+n) x = x*)
   196     fun mk_map_cong0L x mapAsAs sets map_cong0 map_id' =
   197       let
   198         fun mk_prem set f z z' = HOLogic.mk_Trueprop
   199           (mk_Ball (set $ x) (Term.absfree z' (HOLogic.mk_eq (f $ z, z))));
   200         val prems = map4 mk_prem (drop m sets) self_fs zs zs';
   201         val goal = mk_Trueprop_eq (Term.list_comb (mapAsAs, passive_ids @ self_fs) $ x, x);
   202       in
   203         Goal.prove_sorry lthy [] []
   204           (fold_rev Logic.all (x :: self_fs) (Logic.list_implies (prems, goal)))
   205           (K (mk_map_cong0L_tac m map_cong0 map_id'))
   206         |> Thm.close_derivation
   207       end;
   208 
   209     val map_cong0L_thms = map5 mk_map_cong0L xFs mapsAsAs setssAs map_cong0s map_id's;
   210     val in_mono'_thms = map (fn bnf => in_mono_of_bnf bnf OF (replicate m subset_refl)) bnfs;
   211     val in_cong'_thms = map (fn bnf => in_cong_of_bnf bnf OF (replicate m refl)) bnfs;
   212 
   213     val timer = time (timer "Derived simple theorems");
   214 
   215     (* algebra *)
   216 
   217     val alg_bind = Binding.suffix_name ("_" ^ algN) b;
   218     val alg_name = Binding.name_of alg_bind;
   219     val alg_def_bind = (Thm.def_binding alg_bind, []);
   220 
   221     (*forall i = 1 ... n: (\<forall>x \<in> Fi_in A1 .. Am B1 ... Bn. si x \<in> Bi)*)
   222     val alg_spec =
   223       let
   224         val algT = Library.foldr (op -->) (ATs @ BTs @ sTs, HOLogic.boolT);
   225 
   226         val ins = map3 mk_in (replicate n (As @ Bs)) setssAs FTsAs;
   227         fun mk_alg_conjunct B s X x x' =
   228           mk_Ball X (Term.absfree x' (HOLogic.mk_mem (s $ x, B)));
   229 
   230         val lhs = Term.list_comb (Free (alg_name, algT), As @ Bs @ ss);
   231         val rhs = Library.foldr1 HOLogic.mk_conj (map5 mk_alg_conjunct Bs ss ins xFs xFs')
   232       in
   233         mk_Trueprop_eq (lhs, rhs)
   234       end;
   235 
   236     val ((alg_free, (_, alg_def_free)), (lthy, lthy_old)) =
   237         lthy
   238         |> Specification.definition (SOME (alg_bind, NONE, NoSyn), (alg_def_bind, alg_spec))
   239         ||> `Local_Theory.restore;
   240 
   241     val phi = Proof_Context.export_morphism lthy_old lthy;
   242     val alg = fst (Term.dest_Const (Morphism.term phi alg_free));
   243     val alg_def = Morphism.thm phi alg_def_free;
   244 
   245     fun mk_alg As Bs ss =
   246       let
   247         val args = As @ Bs @ ss;
   248         val Ts = map fastype_of args;
   249         val algT = Library.foldr (op -->) (Ts, HOLogic.boolT);
   250       in
   251         Term.list_comb (Const (alg, algT), args)
   252       end;
   253 
   254     val alg_set_thms =
   255       let
   256         val alg_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   257         fun mk_prem x set B = HOLogic.mk_Trueprop (mk_subset (set $ x) B);
   258         fun mk_concl s x B = HOLogic.mk_Trueprop (HOLogic.mk_mem (s $ x, B));
   259         val premss = map2 ((fn x => fn sets =>  map2 (mk_prem x) sets (As @ Bs))) xFs setssAs;
   260         val concls = map3 mk_concl ss xFs Bs;
   261         val goals = map3 (fn x => fn prems => fn concl =>
   262           fold_rev Logic.all (x :: As @ Bs @ ss)
   263             (Logic.list_implies (alg_prem :: prems, concl))) xFs premss concls;
   264       in
   265         map (fn goal =>
   266           Goal.prove_sorry lthy [] [] goal (K (mk_alg_set_tac alg_def)) |> Thm.close_derivation)
   267         goals
   268       end;
   269 
   270     fun mk_talg ATs BTs = mk_alg (map HOLogic.mk_UNIV ATs) (map HOLogic.mk_UNIV BTs);
   271 
   272     val talg_thm =
   273       let
   274         val goal = fold_rev Logic.all ss
   275           (HOLogic.mk_Trueprop (mk_talg passiveAs activeAs ss))
   276       in
   277         Goal.prove_sorry lthy [] [] goal
   278           (K (stac alg_def 1 THEN CONJ_WRAP (K (EVERY' [rtac ballI, rtac UNIV_I] 1)) ss))
   279         |> Thm.close_derivation
   280       end;
   281 
   282     val timer = time (timer "Algebra definition & thms");
   283 
   284     val alg_not_empty_thms =
   285       let
   286         val alg_prem =
   287           HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   288         val concls = map (HOLogic.mk_Trueprop o mk_not_empty) Bs;
   289         val goals =
   290           map (fn concl =>
   291             fold_rev Logic.all (Bs @ ss) (Logic.mk_implies (alg_prem, concl))) concls;
   292       in
   293         map2 (fn goal => fn alg_set =>
   294           Goal.prove_sorry lthy [] []
   295             goal (K (mk_alg_not_empty_tac lthy alg_set alg_set_thms wit_thms))
   296           |> Thm.close_derivation)
   297         goals alg_set_thms
   298       end;
   299 
   300     val timer = time (timer "Proved nonemptiness");
   301 
   302     (* morphism *)
   303 
   304     val mor_bind = Binding.suffix_name ("_" ^ morN) b;
   305     val mor_name = Binding.name_of mor_bind;
   306     val mor_def_bind = (Thm.def_binding mor_bind, []);
   307 
   308     (*fbetw) forall i = 1 ... n: (\<forall>x \<in> Bi. f x \<in> B'i)*)
   309     (*mor) forall i = 1 ... n: (\<forall>x \<in> Fi_in UNIV ... UNIV B1 ... Bn.
   310        f (s1 x) = s1' (Fi_map id ... id f1 ... fn x))*)
   311     val mor_spec =
   312       let
   313         val morT = Library.foldr (op -->) (BTs @ sTs @ B'Ts @ s'Ts @ fTs, HOLogic.boolT);
   314 
   315         fun mk_fbetw f B1 B2 z z' =
   316           mk_Ball B1 (Term.absfree z' (HOLogic.mk_mem (f $ z, B2)));
   317         fun mk_mor sets mapAsBs f s s' T x x' =
   318           mk_Ball (mk_in (passive_UNIVs @ Bs) sets T)
   319             (Term.absfree x' (HOLogic.mk_eq (f $ (s $ x), s' $
   320               (Term.list_comb (mapAsBs, passive_ids @ fs) $ x))));
   321         val lhs = Term.list_comb (Free (mor_name, morT), Bs @ ss @ B's @ s's @ fs);
   322         val rhs = HOLogic.mk_conj
   323           (Library.foldr1 HOLogic.mk_conj (map5 mk_fbetw fs Bs B's zs zs'),
   324           Library.foldr1 HOLogic.mk_conj
   325             (map8 mk_mor setssAs mapsAsBs fs ss s's FTsAs xFs xFs'))
   326       in
   327         mk_Trueprop_eq (lhs, rhs)
   328       end;
   329 
   330     val ((mor_free, (_, mor_def_free)), (lthy, lthy_old)) =
   331         lthy
   332         |> Specification.definition (SOME (mor_bind, NONE, NoSyn), (mor_def_bind, mor_spec))
   333         ||> `Local_Theory.restore;
   334 
   335     val phi = Proof_Context.export_morphism lthy_old lthy;
   336     val mor = fst (Term.dest_Const (Morphism.term phi mor_free));
   337     val mor_def = Morphism.thm phi mor_def_free;
   338 
   339     fun mk_mor Bs1 ss1 Bs2 ss2 fs =
   340       let
   341         val args = Bs1 @ ss1 @ Bs2 @ ss2 @ fs;
   342         val Ts = map fastype_of (Bs1 @ ss1 @ Bs2 @ ss2 @ fs);
   343         val morT = Library.foldr (op -->) (Ts, HOLogic.boolT);
   344       in
   345         Term.list_comb (Const (mor, morT), args)
   346       end;
   347 
   348     val (mor_image_thms, morE_thms) =
   349       let
   350         val prem = HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs);
   351         fun mk_image_goal f B1 B2 = fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs)
   352           (Logic.mk_implies (prem, HOLogic.mk_Trueprop (mk_subset (mk_image f $ B1) B2)));
   353         val image_goals = map3 mk_image_goal fs Bs B's;
   354         fun mk_elim_prem sets x T = HOLogic.mk_Trueprop
   355           (HOLogic.mk_mem (x, mk_in (passive_UNIVs @ Bs) sets T));
   356         fun mk_elim_goal sets mapAsBs f s s' x T =
   357           fold_rev Logic.all (x :: Bs @ ss @ B's @ s's @ fs)
   358             (Logic.list_implies ([prem, mk_elim_prem sets x T],
   359               mk_Trueprop_eq (f $ (s $ x), s' $ Term.list_comb (mapAsBs, passive_ids @ fs @ [x]))));
   360         val elim_goals = map7 mk_elim_goal setssAs mapsAsBs fs ss s's xFs FTsAs;
   361         fun prove goal =
   362           Goal.prove_sorry lthy [] [] goal (K (mk_mor_elim_tac mor_def)) |> Thm.close_derivation;
   363       in
   364         (map prove image_goals, map prove elim_goals)
   365       end;
   366 
   367     val mor_incl_thm =
   368       let
   369         val prems = map2 (HOLogic.mk_Trueprop oo mk_subset) Bs Bs_copy;
   370         val concl = HOLogic.mk_Trueprop (mk_mor Bs ss Bs_copy ss active_ids);
   371       in
   372         Goal.prove_sorry lthy [] []
   373           (fold_rev Logic.all (Bs @ ss @ Bs_copy) (Logic.list_implies (prems, concl)))
   374           (K (mk_mor_incl_tac mor_def map_id's))
   375         |> Thm.close_derivation
   376       end;
   377 
   378     val mor_comp_thm =
   379       let
   380         val prems =
   381           [HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs),
   382            HOLogic.mk_Trueprop (mk_mor B's s's B''s s''s gs)];
   383         val concl =
   384           HOLogic.mk_Trueprop (mk_mor Bs ss B''s s''s (map2 (curry HOLogic.mk_comp) gs fs));
   385       in
   386         Goal.prove_sorry lthy [] []
   387           (fold_rev Logic.all (Bs @ ss @ B's @ s's @ B''s @ s''s @ fs @ gs)
   388              (Logic.list_implies (prems, concl)))
   389           (K (mk_mor_comp_tac mor_def set_map'ss map_comp_id_thms))
   390         |> Thm.close_derivation
   391       end;
   392 
   393     val mor_inv_thm =
   394       let
   395         fun mk_inv_prem f inv_f B B' = HOLogic.mk_conj (mk_subset (mk_image inv_f $ B') B,
   396           HOLogic.mk_conj (mk_inver inv_f f B, mk_inver f inv_f B'));
   397         val prems = map HOLogic.mk_Trueprop
   398           ([mk_mor Bs ss B's s's fs,
   399           mk_alg passive_UNIVs Bs ss,
   400           mk_alg passive_UNIVs B's s's] @
   401           map4 mk_inv_prem fs inv_fs Bs B's);
   402         val concl = HOLogic.mk_Trueprop (mk_mor B's s's Bs ss inv_fs);
   403       in
   404         Goal.prove_sorry lthy [] []
   405           (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs @ inv_fs)
   406             (Logic.list_implies (prems, concl)))
   407           (K (mk_mor_inv_tac alg_def mor_def
   408             set_map'ss morE_thms map_comp_id_thms map_cong0L_thms))
   409         |> Thm.close_derivation
   410       end;
   411 
   412     val mor_cong_thm =
   413       let
   414         val prems = map HOLogic.mk_Trueprop
   415          (map2 (curry HOLogic.mk_eq) fs_copy fs @ [mk_mor Bs ss B's s's fs])
   416         val concl = HOLogic.mk_Trueprop (mk_mor Bs ss B's s's fs_copy);
   417       in
   418         Goal.prove_sorry lthy [] []
   419           (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs @ fs_copy)
   420              (Logic.list_implies (prems, concl)))
   421           (K ((hyp_subst_tac lthy THEN' atac) 1))
   422         |> Thm.close_derivation
   423       end;
   424 
   425     val mor_str_thm =
   426       let
   427         val maps = map2 (fn Ds => fn bnf => Term.list_comb
   428           (mk_map_of_bnf Ds (passiveAs @ FTsAs) allAs bnf, passive_ids @ ss)) Dss bnfs;
   429       in
   430         Goal.prove_sorry lthy [] []
   431           (fold_rev Logic.all ss (HOLogic.mk_Trueprop
   432             (mk_mor (map HOLogic.mk_UNIV FTsAs) maps active_UNIVs ss ss)))
   433           (K (mk_mor_str_tac ks mor_def))
   434         |> Thm.close_derivation
   435       end;
   436 
   437     val mor_convol_thm =
   438       let
   439         val maps = map3 (fn s => fn prod_s => fn mapx =>
   440           mk_convol (HOLogic.mk_comp (s, Term.list_comb (mapx, passive_ids @ fsts)), prod_s))
   441           s's prod_ss map_fsts;
   442       in
   443         Goal.prove_sorry lthy [] []
   444           (fold_rev Logic.all (s's @ prod_ss) (HOLogic.mk_Trueprop
   445             (mk_mor prod_UNIVs maps (map HOLogic.mk_UNIV activeBs) s's fsts)))
   446           (K (mk_mor_convol_tac ks mor_def))
   447         |> Thm.close_derivation
   448       end;
   449 
   450     val mor_UNIV_thm =
   451       let
   452         fun mk_conjunct mapAsBs f s s' = HOLogic.mk_eq
   453             (HOLogic.mk_comp (f, s),
   454             HOLogic.mk_comp (s', Term.list_comb (mapAsBs, passive_ids @ fs)));
   455         val lhs = mk_mor active_UNIVs ss (map HOLogic.mk_UNIV activeBs) s's fs;
   456         val rhs = Library.foldr1 HOLogic.mk_conj (map4 mk_conjunct mapsAsBs fs ss s's);
   457       in
   458         Goal.prove_sorry lthy [] [] (fold_rev Logic.all (ss @ s's @ fs) (mk_Trueprop_eq (lhs, rhs)))
   459           (K (mk_mor_UNIV_tac m morE_thms mor_def))
   460         |> Thm.close_derivation
   461       end;
   462 
   463     val timer = time (timer "Morphism definition & thms");
   464 
   465     (* isomorphism *)
   466 
   467     (*mor Bs1 ss1 Bs2 ss2 fs \<and> (\<exists>gs. mor Bs2 ss2 Bs1 ss1 fs \<and>
   468        forall i = 1 ... n. (inver gs[i] fs[i] Bs1[i] \<and> inver fs[i] gs[i] Bs2[i]))*)
   469     fun mk_iso Bs1 ss1 Bs2 ss2 fs gs =
   470       let
   471         val ex_inv_mor = list_exists_free gs
   472           (HOLogic.mk_conj (mk_mor Bs2 ss2 Bs1 ss1 gs,
   473             Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_conj)
   474               (map3 mk_inver gs fs Bs1) (map3 mk_inver fs gs Bs2))));
   475       in
   476         HOLogic.mk_conj (mk_mor Bs1 ss1 Bs2 ss2 fs, ex_inv_mor)
   477       end;
   478 
   479     val iso_alt_thm =
   480       let
   481         val prems = map HOLogic.mk_Trueprop
   482          [mk_alg passive_UNIVs Bs ss,
   483          mk_alg passive_UNIVs B's s's]
   484         val concl = mk_Trueprop_eq (mk_iso Bs ss B's s's fs inv_fs,
   485           HOLogic.mk_conj (mk_mor Bs ss B's s's fs,
   486             Library.foldr1 HOLogic.mk_conj (map3 mk_bij_betw fs Bs B's)));
   487       in
   488         Goal.prove_sorry lthy [] []
   489           (fold_rev Logic.all (Bs @ ss @ B's @ s's @ fs) (Logic.list_implies (prems, concl)))
   490           (K (mk_iso_alt_tac mor_image_thms mor_inv_thm))
   491         |> Thm.close_derivation
   492       end;
   493 
   494     val timer = time (timer "Isomorphism definition & thms");
   495 
   496     (* algebra copies *)
   497 
   498     val (copy_alg_thm, ex_copy_alg_thm) =
   499       let
   500         val prems = map HOLogic.mk_Trueprop
   501          (mk_alg passive_UNIVs Bs ss :: map3 mk_bij_betw inv_fs B's Bs);
   502         val inver_prems = map HOLogic.mk_Trueprop
   503           (map3 mk_inver inv_fs fs Bs @ map3 mk_inver fs inv_fs B's);
   504         val all_prems = prems @ inver_prems;
   505         fun mk_s f s mapT y y' = Term.absfree y' (f $ (s $
   506           (Term.list_comb (mapT, passive_ids @ inv_fs) $ y)));
   507 
   508         val alg = HOLogic.mk_Trueprop
   509           (mk_alg passive_UNIVs B's (map5 mk_s fs ss mapsBsAs yFs yFs'));
   510         val copy_str_thm = Goal.prove_sorry lthy [] []
   511           (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   512             (Logic.list_implies (all_prems, alg)))
   513           (K (mk_copy_str_tac set_map'ss alg_def alg_set_thms))
   514           |> Thm.close_derivation;
   515 
   516         val iso = HOLogic.mk_Trueprop
   517           (mk_iso B's (map5 mk_s fs ss mapsBsAs yFs yFs') Bs ss inv_fs fs_copy);
   518         val copy_alg_thm = Goal.prove_sorry lthy [] []
   519           (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   520             (Logic.list_implies (all_prems, iso)))
   521           (K (mk_copy_alg_tac set_map'ss alg_set_thms mor_def iso_alt_thm copy_str_thm))
   522           |> Thm.close_derivation;
   523 
   524         val ex = HOLogic.mk_Trueprop
   525           (list_exists_free s's
   526             (HOLogic.mk_conj (mk_alg passive_UNIVs B's s's,
   527               mk_iso B's s's Bs ss inv_fs fs_copy)));
   528         val ex_copy_alg_thm = Goal.prove_sorry lthy [] []
   529           (fold_rev Logic.all (Bs @ ss @ B's @ inv_fs @ fs)
   530              (Logic.list_implies (prems, ex)))
   531           (K (mk_ex_copy_alg_tac n copy_str_thm copy_alg_thm))
   532           |> Thm.close_derivation;
   533       in
   534         (copy_alg_thm, ex_copy_alg_thm)
   535       end;
   536 
   537     val timer = time (timer "Copy thms");
   538 
   539 
   540     (* bounds *)
   541 
   542     val sum_Card_order = if n = 1 then bd_Card_order else @{thm Card_order_csum};
   543     val sum_Cnotzero = if n = 1 then bd_Cnotzero else bd_Cnotzero RS @{thm csum_Cnotzero1};
   544     val sum_Cinfinite = if n = 1 then bd_Cinfinite else bd_Cinfinite RS @{thm Cinfinite_csum1};
   545     fun mk_set_bd_sums i bd_Card_order bds =
   546       if n = 1 then bds
   547       else map (fn thm => bd_Card_order RS mk_ordLeq_csum n i thm) bds;
   548     val set_bd_sumss = map3 mk_set_bd_sums ks bd_Card_orders set_bdss;
   549 
   550     fun mk_in_bd_sum i Co Cnz bd =
   551       if n = 1 then bd
   552       else Cnz RS ((Co RS mk_ordLeq_csum n i (Co RS @{thm ordLeq_refl})) RS
   553         (bd RS @{thm ordLeq_transitive[OF _ cexp_mono2_Cnotzero[OF _ Card_order_csum]]}));
   554     val in_bd_sums = map4 mk_in_bd_sum ks bd_Card_orders bd_Cnotzeros in_bds;
   555 
   556     val sum_bd = Library.foldr1 (uncurry mk_csum) bds;
   557     val suc_bd = mk_cardSuc sum_bd;
   558     val field_suc_bd = mk_Field suc_bd;
   559     val suc_bdT = fst (dest_relT (fastype_of suc_bd));
   560     fun mk_Asuc_bd [] = mk_cexp ctwo suc_bd
   561       | mk_Asuc_bd As =
   562         mk_cexp (mk_csum (Library.foldr1 (uncurry mk_csum) (map mk_card_of As)) ctwo) suc_bd;
   563 
   564     val suc_bd_Card_order = if n = 1 then bd_Card_order RS @{thm cardSuc_Card_order}
   565       else @{thm cardSuc_Card_order[OF Card_order_csum]};
   566     val suc_bd_Cinfinite = if n = 1 then bd_Cinfinite RS @{thm Cinfinite_cardSuc}
   567       else bd_Cinfinite RS @{thm Cinfinite_cardSuc[OF Cinfinite_csum1]};
   568     val suc_bd_Cnotzero = suc_bd_Cinfinite RS @{thm Cinfinite_Cnotzero};
   569     val suc_bd_worel = suc_bd_Card_order RS @{thm Card_order_wo_rel}
   570     val basis_Asuc = if m = 0 then @{thm ordLeq_refl[OF Card_order_ctwo]}
   571         else @{thm ordLeq_csum2[OF Card_order_ctwo]};
   572     val Asuc_bd_Cinfinite = suc_bd_Cinfinite RS (basis_Asuc RS @{thm Cinfinite_cexp});
   573 
   574     val suc_bd_Asuc_bd = @{thm ordLess_ordLeq_trans[OF ordLess_ctwo_cexp cexp_mono1]} OF
   575       [suc_bd_Card_order, basis_Asuc, suc_bd_Card_order];
   576 
   577     val Asuc_bdT = fst (dest_relT (fastype_of (mk_Asuc_bd As)));
   578     val II_BTs = replicate n (HOLogic.mk_setT Asuc_bdT);
   579     val II_sTs = map2 (fn Ds => fn bnf =>
   580       mk_T_of_bnf Ds (passiveAs @ replicate n Asuc_bdT) bnf --> Asuc_bdT) Dss bnfs;
   581 
   582     val (((((((idxs, Asi_name), (idx, idx')), (jdx, jdx')), II_Bs), II_ss), Asuc_fs),
   583       names_lthy) = names_lthy
   584       |> mk_Frees "i" (replicate n suc_bdT)
   585       ||>> (fn ctxt => apfst the_single (mk_fresh_names ctxt 1 "Asi"))
   586       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "i") suc_bdT
   587       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "j") suc_bdT
   588       ||>> mk_Frees "IIB" II_BTs
   589       ||>> mk_Frees "IIs" II_sTs
   590       ||>> mk_Frees "f" (map (fn T => Asuc_bdT --> T) activeAs);
   591 
   592     val suc_bd_limit_thm =
   593       let
   594         val prem = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
   595           (map (fn idx => HOLogic.mk_mem (idx, field_suc_bd)) idxs));
   596         fun mk_conjunct idx = HOLogic.mk_conj (mk_not_eq idx jdx,
   597           HOLogic.mk_mem (HOLogic.mk_prod (idx, jdx), suc_bd));
   598         val concl = HOLogic.mk_Trueprop (mk_Bex field_suc_bd
   599           (Term.absfree jdx' (Library.foldr1 HOLogic.mk_conj (map mk_conjunct idxs))));
   600       in
   601         Goal.prove_sorry lthy [] []
   602           (fold_rev Logic.all idxs (Logic.list_implies ([prem], concl)))
   603           (K (mk_bd_limit_tac n suc_bd_Cinfinite))
   604         |> Thm.close_derivation
   605       end;
   606 
   607     val timer = time (timer "Bounds");
   608 
   609 
   610     (* minimal algebra *)
   611 
   612     fun mk_minG Asi i k = mk_UNION (mk_underS suc_bd $ i)
   613       (Term.absfree jdx' (mk_nthN n (Asi $ jdx) k));
   614 
   615     fun mk_minH_component As Asi i sets Ts s k =
   616       HOLogic.mk_binop @{const_name "sup"}
   617       (mk_minG Asi i k, mk_image s $ mk_in (As @ map (mk_minG Asi i) ks) sets Ts);
   618 
   619     fun mk_min_algs As ss =
   620       let
   621         val BTs = map (range_type o fastype_of) ss;
   622         val Ts = map (HOLogic.dest_setT o fastype_of) As @ BTs;
   623         val (Asi, Asi') = `Free (Asi_name, suc_bdT -->
   624           Library.foldr1 HOLogic.mk_prodT (map HOLogic.mk_setT BTs));
   625       in
   626          mk_worec suc_bd (Term.absfree Asi' (Term.absfree idx' (HOLogic.mk_tuple
   627            (map4 (mk_minH_component As Asi idx) (mk_setss Ts) (mk_FTs Ts) ss ks))))
   628       end;
   629 
   630     val (min_algs_thms, min_algs_mono_thms, card_of_min_algs_thm, least_min_algs_thm) =
   631       let
   632         val i_field = HOLogic.mk_mem (idx, field_suc_bd);
   633         val min_algs = mk_min_algs As ss;
   634         val min_algss = map (fn k => mk_nthN n (min_algs $ idx) k) ks;
   635 
   636         val concl = HOLogic.mk_Trueprop
   637           (HOLogic.mk_eq (min_algs $ idx, HOLogic.mk_tuple
   638             (map4 (mk_minH_component As min_algs idx) setssAs FTsAs ss ks)));
   639         val goal = fold_rev Logic.all (idx :: As @ ss)
   640           (Logic.mk_implies (HOLogic.mk_Trueprop i_field, concl));
   641 
   642         val min_algs_thm = Goal.prove_sorry lthy [] [] goal
   643           (K (mk_min_algs_tac suc_bd_worel in_cong'_thms))
   644           |> Thm.close_derivation;
   645 
   646         val min_algs_thms = map (fn k => min_algs_thm RS mk_nthI n k) ks;
   647 
   648         fun mk_mono_goal min_alg =
   649           fold_rev Logic.all (As @ ss) (HOLogic.mk_Trueprop (mk_relChain suc_bd
   650             (Term.absfree idx' min_alg)));
   651 
   652         val monos =
   653           map2 (fn goal => fn min_algs =>
   654             Goal.prove_sorry lthy [] [] goal (K (mk_min_algs_mono_tac lthy min_algs))
   655             |> Thm.close_derivation)
   656           (map mk_mono_goal min_algss) min_algs_thms;
   657 
   658         val Asuc_bd = mk_Asuc_bd As;
   659 
   660         fun mk_card_conjunct min_alg = mk_ordLeq (mk_card_of min_alg) Asuc_bd;
   661         val card_conjunction = Library.foldr1 HOLogic.mk_conj (map mk_card_conjunct min_algss);
   662         val card_cT = certifyT lthy suc_bdT;
   663         val card_ct = certify lthy (Term.absfree idx' card_conjunction);
   664 
   665         val card_of = singleton (Proof_Context.export names_lthy lthy)
   666           (Goal.prove_sorry lthy [] []
   667             (HOLogic.mk_Trueprop (HOLogic.mk_imp (i_field, card_conjunction)))
   668             (K (mk_min_algs_card_of_tac card_cT card_ct
   669               m suc_bd_worel min_algs_thms in_bd_sums
   670               sum_Card_order sum_Cnotzero suc_bd_Card_order suc_bd_Cinfinite suc_bd_Cnotzero
   671               suc_bd_Asuc_bd Asuc_bd_Cinfinite)))
   672           |> Thm.close_derivation;
   673 
   674         val least_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   675         val least_conjunction = Library.foldr1 HOLogic.mk_conj (map2 mk_subset min_algss Bs);
   676         val least_cT = certifyT lthy suc_bdT;
   677         val least_ct = certify lthy (Term.absfree idx' least_conjunction);
   678 
   679         val least = singleton (Proof_Context.export names_lthy lthy)
   680           (Goal.prove_sorry lthy [] []
   681             (Logic.mk_implies (least_prem,
   682               HOLogic.mk_Trueprop (HOLogic.mk_imp (i_field, least_conjunction))))
   683             (K (mk_min_algs_least_tac least_cT least_ct
   684               suc_bd_worel min_algs_thms alg_set_thms)))
   685           |> Thm.close_derivation;
   686       in
   687         (min_algs_thms, monos, card_of, least)
   688       end;
   689 
   690     val timer = time (timer "min_algs definition & thms");
   691 
   692     fun min_alg_bind i = Binding.suffix_name
   693       ("_" ^ min_algN ^ (if n = 1 then "" else string_of_int i)) b;
   694     val min_alg_name = Binding.name_of o min_alg_bind;
   695     val min_alg_def_bind = rpair [] o Thm.def_binding o min_alg_bind;
   696 
   697     fun min_alg_spec i =
   698       let
   699         val min_algT =
   700           Library.foldr (op -->) (ATs @ sTs, HOLogic.mk_setT (nth activeAs (i - 1)));
   701 
   702         val lhs = Term.list_comb (Free (min_alg_name i, min_algT), As @ ss);
   703         val rhs = mk_UNION (field_suc_bd)
   704           (Term.absfree idx' (mk_nthN n (mk_min_algs As ss $ idx) i));
   705       in
   706         mk_Trueprop_eq (lhs, rhs)
   707       end;
   708 
   709     val ((min_alg_frees, (_, min_alg_def_frees)), (lthy, lthy_old)) =
   710         lthy
   711         |> fold_map (fn i => Specification.definition
   712           (SOME (min_alg_bind i, NONE, NoSyn), (min_alg_def_bind i, min_alg_spec i))) ks
   713         |>> apsnd split_list o split_list
   714         ||> `Local_Theory.restore;
   715 
   716     val phi = Proof_Context.export_morphism lthy_old lthy;
   717     val min_algs = map (fst o Term.dest_Const o Morphism.term phi) min_alg_frees;
   718     val min_alg_defs = map (Morphism.thm phi) min_alg_def_frees;
   719 
   720     fun mk_min_alg As ss i =
   721       let
   722         val T = HOLogic.mk_setT (range_type (fastype_of (nth ss (i - 1))))
   723         val args = As @ ss;
   724         val Ts = map fastype_of args;
   725         val min_algT = Library.foldr (op -->) (Ts, T);
   726       in
   727         Term.list_comb (Const (nth min_algs (i - 1), min_algT), args)
   728       end;
   729 
   730     val (alg_min_alg_thm, card_of_min_alg_thms, least_min_alg_thms, mor_incl_min_alg_thm) =
   731       let
   732         val min_algs = map (mk_min_alg As ss) ks;
   733 
   734         val goal = fold_rev Logic.all (As @ ss) (HOLogic.mk_Trueprop (mk_alg As min_algs ss));
   735         val alg_min_alg = Goal.prove_sorry lthy [] [] goal
   736           (K (mk_alg_min_alg_tac m alg_def min_alg_defs suc_bd_limit_thm sum_Cinfinite
   737             set_bd_sumss min_algs_thms min_algs_mono_thms))
   738           |> Thm.close_derivation;
   739 
   740         val Asuc_bd = mk_Asuc_bd As;
   741         fun mk_card_of_thm min_alg def = Goal.prove_sorry lthy [] []
   742           (fold_rev Logic.all (As @ ss)
   743             (HOLogic.mk_Trueprop (mk_ordLeq (mk_card_of min_alg) Asuc_bd)))
   744           (K (mk_card_of_min_alg_tac def card_of_min_algs_thm
   745             suc_bd_Card_order suc_bd_Asuc_bd Asuc_bd_Cinfinite))
   746           |> Thm.close_derivation;
   747 
   748         val least_prem = HOLogic.mk_Trueprop (mk_alg As Bs ss);
   749         fun mk_least_thm min_alg B def = Goal.prove_sorry lthy [] []
   750           (fold_rev Logic.all (As @ Bs @ ss)
   751             (Logic.mk_implies (least_prem, HOLogic.mk_Trueprop (mk_subset min_alg B))))
   752           (K (mk_least_min_alg_tac def least_min_algs_thm))
   753           |> Thm.close_derivation;
   754 
   755         val leasts = map3 mk_least_thm min_algs Bs min_alg_defs;
   756 
   757         val incl_prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   758         val incl_min_algs = map (mk_min_alg passive_UNIVs ss) ks;
   759         val incl = Goal.prove_sorry lthy [] []
   760           (fold_rev Logic.all (Bs @ ss)
   761             (Logic.mk_implies (incl_prem,
   762               HOLogic.mk_Trueprop (mk_mor incl_min_algs ss Bs ss active_ids))))
   763           (K (EVERY' (rtac mor_incl_thm :: map etac leasts) 1))
   764           |> Thm.close_derivation;
   765       in
   766         (alg_min_alg, map2 mk_card_of_thm min_algs min_alg_defs, leasts, incl)
   767       end;
   768 
   769     val timer = time (timer "Minimal algebra definition & thms");
   770 
   771     val II_repT = HOLogic.mk_prodT (HOLogic.mk_tupleT II_BTs, HOLogic.mk_tupleT II_sTs);
   772     val IIT_bind = Binding.suffix_name ("_" ^ IITN) b;
   773 
   774     val ((IIT_name, (IIT_glob_info, IIT_loc_info)), lthy) =
   775       typedef (IIT_bind, params, NoSyn)
   776         (HOLogic.mk_UNIV II_repT) NONE (EVERY' [rtac exI, rtac UNIV_I] 1) lthy;
   777 
   778     val IIT = Type (IIT_name, params');
   779     val Abs_IIT = Const (#Abs_name IIT_glob_info, II_repT --> IIT);
   780     val Rep_IIT = Const (#Rep_name IIT_glob_info, IIT --> II_repT);
   781     val Abs_IIT_inverse_thm = UNIV_I RS #Abs_inverse IIT_loc_info;
   782 
   783     val initT = IIT --> Asuc_bdT;
   784     val active_initTs = replicate n initT;
   785     val init_FTs = map2 (fn Ds => mk_T_of_bnf Ds (passiveAs @ active_initTs)) Dss bnfs;
   786     val init_fTs = map (fn T => initT --> T) activeAs;
   787 
   788     val (((((((iidx, iidx'), init_xs), (init_xFs, init_xFs')),
   789       init_fs), init_fs_copy), init_phis), names_lthy) = names_lthy
   790       |> yield_singleton (apfst (op ~~) oo mk_Frees' "i") IIT
   791       ||>> mk_Frees "ix" active_initTs
   792       ||>> mk_Frees' "x" init_FTs
   793       ||>> mk_Frees "f" init_fTs
   794       ||>> mk_Frees "f" init_fTs
   795       ||>> mk_Frees "P" (replicate n (mk_pred1T initT));
   796 
   797     val II = HOLogic.mk_Collect (fst iidx', IIT, list_exists_free (II_Bs @ II_ss)
   798       (HOLogic.mk_conj (HOLogic.mk_eq (iidx,
   799         Abs_IIT $ (HOLogic.mk_prod (HOLogic.mk_tuple II_Bs, HOLogic.mk_tuple II_ss))),
   800         mk_alg passive_UNIVs II_Bs II_ss)));
   801 
   802     val select_Bs = map (mk_nthN n (HOLogic.mk_fst (Rep_IIT $ iidx))) ks;
   803     val select_ss = map (mk_nthN n (HOLogic.mk_snd (Rep_IIT $ iidx))) ks;
   804 
   805     fun str_init_bind i = Binding.suffix_name ("_" ^ str_initN ^ (if n = 1 then "" else
   806       string_of_int i)) b;
   807     val str_init_name = Binding.name_of o str_init_bind;
   808     val str_init_def_bind = rpair [] o Thm.def_binding o str_init_bind;
   809 
   810     fun str_init_spec i =
   811       let
   812         val T = nth init_FTs (i - 1);
   813         val init_xF = nth init_xFs (i - 1)
   814         val select_s = nth select_ss (i - 1);
   815         val map = mk_map_of_bnf (nth Dss (i - 1))
   816           (passiveAs @ active_initTs) (passiveAs @ replicate n Asuc_bdT)
   817           (nth bnfs (i - 1));
   818         val map_args = passive_ids @ replicate n (mk_rapp iidx Asuc_bdT);
   819         val str_initT = T --> IIT --> Asuc_bdT;
   820 
   821         val lhs = Term.list_comb (Free (str_init_name i, str_initT), [init_xF, iidx]);
   822         val rhs = select_s $ (Term.list_comb (map, map_args) $ init_xF);
   823       in
   824         mk_Trueprop_eq (lhs, rhs)
   825       end;
   826 
   827     val ((str_init_frees, (_, str_init_def_frees)), (lthy, lthy_old)) =
   828       lthy
   829       |> fold_map (fn i => Specification.definition
   830         (SOME (str_init_bind i, NONE, NoSyn), (str_init_def_bind i, str_init_spec i))) ks
   831       |>> apsnd split_list o split_list
   832       ||> `Local_Theory.restore;
   833 
   834     val phi = Proof_Context.export_morphism lthy_old lthy;
   835     val str_inits =
   836       map (Term.subst_atomic_types (map (`(Morphism.typ phi)) params') o Morphism.term phi)
   837         str_init_frees;
   838 
   839     val str_init_defs = map (Morphism.thm phi) str_init_def_frees;
   840 
   841     val car_inits = map (mk_min_alg passive_UNIVs str_inits) ks;
   842 
   843     (*TODO: replace with instantiate? (problem: figure out right type instantiation)*)
   844     val alg_init_thm = Goal.prove_sorry lthy [] []
   845       (HOLogic.mk_Trueprop (mk_alg passive_UNIVs car_inits str_inits))
   846       (K (rtac alg_min_alg_thm 1))
   847       |> Thm.close_derivation;
   848 
   849     val alg_select_thm = Goal.prove_sorry lthy [] []
   850       (HOLogic.mk_Trueprop (mk_Ball II
   851         (Term.absfree iidx' (mk_alg passive_UNIVs select_Bs select_ss))))
   852       (mk_alg_select_tac Abs_IIT_inverse_thm)
   853       |> Thm.close_derivation;
   854 
   855     val mor_select_thm =
   856       let
   857         val alg_prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   858         val i_prem = HOLogic.mk_Trueprop (HOLogic.mk_mem (iidx, II));
   859         val mor_prem = HOLogic.mk_Trueprop (mk_mor select_Bs select_ss Bs ss Asuc_fs);
   860         val prems = [alg_prem, i_prem, mor_prem];
   861         val concl = HOLogic.mk_Trueprop
   862           (mk_mor car_inits str_inits Bs ss
   863             (map (fn f => HOLogic.mk_comp (f, mk_rapp iidx Asuc_bdT)) Asuc_fs));
   864       in
   865         Goal.prove_sorry lthy [] []
   866           (fold_rev Logic.all (iidx :: Bs @ ss @ Asuc_fs) (Logic.list_implies (prems, concl)))
   867           (K (mk_mor_select_tac mor_def mor_cong_thm mor_comp_thm mor_incl_min_alg_thm alg_def
   868             alg_select_thm alg_set_thms set_map'ss str_init_defs))
   869         |> Thm.close_derivation
   870       end;
   871 
   872     val (init_ex_mor_thm, init_unique_mor_thms) =
   873       let
   874         val prem = HOLogic.mk_Trueprop (mk_alg passive_UNIVs Bs ss);
   875         val concl = HOLogic.mk_Trueprop
   876           (list_exists_free init_fs (mk_mor car_inits str_inits Bs ss init_fs));
   877         val ex_mor = Goal.prove_sorry lthy [] []
   878           (fold_rev Logic.all (Bs @ ss) (Logic.mk_implies (prem, concl)))
   879           (mk_init_ex_mor_tac Abs_IIT_inverse_thm ex_copy_alg_thm alg_min_alg_thm
   880             card_of_min_alg_thms mor_comp_thm mor_select_thm mor_incl_min_alg_thm)
   881           |> Thm.close_derivation;
   882 
   883         val prems = map2 (HOLogic.mk_Trueprop oo curry HOLogic.mk_mem) init_xs car_inits
   884         val mor_prems = map HOLogic.mk_Trueprop
   885           [mk_mor car_inits str_inits Bs ss init_fs,
   886           mk_mor car_inits str_inits Bs ss init_fs_copy];
   887         fun mk_fun_eq f g x = HOLogic.mk_eq (f $ x, g $ x);
   888         val unique = HOLogic.mk_Trueprop
   889           (Library.foldr1 HOLogic.mk_conj (map3 mk_fun_eq init_fs init_fs_copy init_xs));
   890         val unique_mor = Goal.prove_sorry lthy [] []
   891           (fold_rev Logic.all (init_xs @ Bs @ ss @ init_fs @ init_fs_copy)
   892             (Logic.list_implies (prems @ mor_prems, unique)))
   893           (K (mk_init_unique_mor_tac m alg_def alg_init_thm least_min_alg_thms
   894             in_mono'_thms alg_set_thms morE_thms map_cong0s))
   895           |> Thm.close_derivation;
   896       in
   897         (ex_mor, split_conj_thm unique_mor)
   898       end;
   899 
   900     val init_setss = mk_setss (passiveAs @ active_initTs);
   901     val active_init_setss = map (drop m) init_setss;
   902     val init_ins = map2 (fn sets => mk_in (passive_UNIVs @ car_inits) sets) init_setss init_FTs;
   903 
   904     fun mk_closed phis =
   905       let
   906         fun mk_conjunct phi str_init init_sets init_in x x' =
   907           let
   908             val prem = Library.foldr1 HOLogic.mk_conj
   909               (map2 (fn set => mk_Ball (set $ x)) init_sets phis);
   910             val concl = phi $ (str_init $ x);
   911           in
   912             mk_Ball init_in (Term.absfree x' (HOLogic.mk_imp (prem, concl)))
   913           end;
   914       in
   915         Library.foldr1 HOLogic.mk_conj
   916           (map6 mk_conjunct phis str_inits active_init_setss init_ins init_xFs init_xFs')
   917       end;
   918 
   919     val init_induct_thm =
   920       let
   921         val prem = HOLogic.mk_Trueprop (mk_closed init_phis);
   922         val concl = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
   923           (map2 mk_Ball car_inits init_phis));
   924       in
   925         Goal.prove_sorry lthy [] []
   926           (fold_rev Logic.all init_phis (Logic.mk_implies (prem, concl)))
   927           (K (mk_init_induct_tac m alg_def alg_init_thm least_min_alg_thms alg_set_thms))
   928         |> Thm.close_derivation
   929       end;
   930 
   931     val timer = time (timer "Initiality definition & thms");
   932 
   933     val ((T_names, (T_glob_infos, T_loc_infos)), lthy) =
   934       lthy
   935       |> fold_map3 (fn b => fn mx => fn car_init => typedef (b, params, mx) car_init NONE
   936           (EVERY' [rtac ssubst, rtac @{thm ex_in_conv}, resolve_tac alg_not_empty_thms,
   937             rtac alg_init_thm] 1)) bs mixfixes car_inits
   938       |>> apsnd split_list o split_list;
   939 
   940     val Ts = map (fn name => Type (name, params')) T_names;
   941     fun mk_Ts passive = map (Term.typ_subst_atomic (passiveAs ~~ passive)) Ts;
   942     val Ts' = mk_Ts passiveBs;
   943     val Rep_Ts = map2 (fn info => fn T => Const (#Rep_name info, T --> initT)) T_glob_infos Ts;
   944     val Abs_Ts = map2 (fn info => fn T => Const (#Abs_name info, initT --> T)) T_glob_infos Ts;
   945 
   946     val type_defs = map #type_definition T_loc_infos;
   947     val Reps = map #Rep T_loc_infos;
   948     val Rep_casess = map #Rep_cases T_loc_infos;
   949     val Rep_injects = map #Rep_inject T_loc_infos;
   950     val Rep_inverses = map #Rep_inverse T_loc_infos;
   951     val Abs_inverses = map #Abs_inverse T_loc_infos;
   952 
   953     fun mk_inver_thm mk_tac rep abs X thm =
   954       Goal.prove_sorry lthy [] []
   955         (HOLogic.mk_Trueprop (mk_inver rep abs X))
   956         (K (EVERY' [rtac ssubst, rtac @{thm inver_def}, rtac ballI, mk_tac thm] 1))
   957       |> Thm.close_derivation;
   958 
   959     val inver_Reps = map4 (mk_inver_thm rtac) Abs_Ts Rep_Ts (map HOLogic.mk_UNIV Ts) Rep_inverses;
   960     val inver_Abss = map4 (mk_inver_thm etac) Rep_Ts Abs_Ts car_inits Abs_inverses;
   961 
   962     val timer = time (timer "THE TYPEDEFs & Rep/Abs thms");
   963 
   964     val UNIVs = map HOLogic.mk_UNIV Ts;
   965     val FTs = mk_FTs (passiveAs @ Ts);
   966     val FTs' = mk_FTs (passiveBs @ Ts');
   967     fun mk_set_Ts T = passiveAs @ replicate n (HOLogic.mk_setT T);
   968     val setFTss = map (mk_FTs o mk_set_Ts) passiveAs;
   969     val FTs_setss = mk_setss (passiveAs @ Ts);
   970     val FTs'_setss = mk_setss (passiveBs @ Ts');
   971     val map_FT_inits = map2 (fn Ds =>
   972       mk_map_of_bnf Ds (passiveAs @ Ts) (passiveAs @ active_initTs)) Dss bnfs;
   973     val fTs = map2 (curry op -->) Ts activeAs;
   974     val foldT = Library.foldr1 HOLogic.mk_prodT (map2 (curry op -->) Ts activeAs);
   975     val rec_sTs = map (Term.typ_subst_atomic (activeBs ~~ Ts)) prod_sTs;
   976     val rec_maps = map (Term.subst_atomic_types (activeBs ~~ Ts)) map_fsts;
   977     val rec_maps_rev = map (Term.subst_atomic_types (activeBs ~~ Ts)) map_fsts_rev;
   978     val rec_fsts = map (Term.subst_atomic_types (activeBs ~~ Ts)) fsts;
   979     val rec_UNIVs = map2 (HOLogic.mk_UNIV oo curry HOLogic.mk_prodT) Ts activeAs;
   980 
   981     val (((((((((Izs1, Izs1'), (Izs2, Izs2')), (xFs, xFs')), yFs), (AFss, AFss')),
   982       (fold_f, fold_f')), fs), rec_ss), names_lthy) = names_lthy
   983       |> mk_Frees' "z1" Ts
   984       ||>> mk_Frees' "z2" Ts'
   985       ||>> mk_Frees' "x" FTs
   986       ||>> mk_Frees "y" FTs'
   987       ||>> mk_Freess' "z" setFTss
   988       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "f") foldT
   989       ||>> mk_Frees "f" fTs
   990       ||>> mk_Frees "s" rec_sTs;
   991 
   992     val Izs = map2 retype_free Ts zs;
   993     val phis = map2 retype_free (map mk_pred1T Ts) init_phis;
   994     val phi2s = map2 retype_free (map2 mk_pred2T Ts Ts') init_phis;
   995 
   996     fun ctor_bind i = Binding.suffix_name ("_" ^ ctorN) (nth bs (i - 1));
   997     val ctor_name = Binding.name_of o ctor_bind;
   998     val ctor_def_bind = rpair [] o Thm.def_binding o ctor_bind;
   999 
  1000     fun ctor_spec i abs str map_FT_init x x' =
  1001       let
  1002         val ctorT = nth FTs (i - 1) --> nth Ts (i - 1);
  1003 
  1004         val lhs = Free (ctor_name i, ctorT);
  1005         val rhs = Term.absfree x' (abs $ (str $
  1006           (Term.list_comb (map_FT_init, map HOLogic.id_const passiveAs @ Rep_Ts) $ x)));
  1007       in
  1008         mk_Trueprop_eq (lhs, rhs)
  1009       end;
  1010 
  1011     val ((ctor_frees, (_, ctor_def_frees)), (lthy, lthy_old)) =
  1012       lthy
  1013       |> fold_map6 (fn i => fn abs => fn str => fn mapx => fn x => fn x' =>
  1014         Specification.definition
  1015           (SOME (ctor_bind i, NONE, NoSyn), (ctor_def_bind i, ctor_spec i abs str mapx x x')))
  1016           ks Abs_Ts str_inits map_FT_inits xFs xFs'
  1017       |>> apsnd split_list o split_list
  1018       ||> `Local_Theory.restore;
  1019 
  1020     val phi = Proof_Context.export_morphism lthy_old lthy;
  1021     fun mk_ctors passive =
  1022       map (Term.subst_atomic_types (map (Morphism.typ phi) params' ~~ (mk_params passive)) o
  1023         Morphism.term phi) ctor_frees;
  1024     val ctors = mk_ctors passiveAs;
  1025     val ctor's = mk_ctors passiveBs;
  1026     val ctor_defs = map (Morphism.thm phi) ctor_def_frees;
  1027 
  1028     val (mor_Rep_thm, mor_Abs_thm) =
  1029       let
  1030         val copy = alg_init_thm RS copy_alg_thm;
  1031         fun mk_bij inj Rep cases = @{thm bij_betwI'} OF [inj, Rep, cases];
  1032         val bijs = map3 mk_bij Rep_injects Reps Rep_casess;
  1033         val mor_Rep =
  1034           Goal.prove_sorry lthy [] []
  1035             (HOLogic.mk_Trueprop (mk_mor UNIVs ctors car_inits str_inits Rep_Ts))
  1036             (mk_mor_Rep_tac ctor_defs copy bijs inver_Abss inver_Reps)
  1037           |> Thm.close_derivation;
  1038 
  1039         val inv = mor_inv_thm OF [mor_Rep, talg_thm, alg_init_thm];
  1040         val mor_Abs =
  1041           Goal.prove_sorry lthy [] []
  1042             (HOLogic.mk_Trueprop (mk_mor car_inits str_inits UNIVs ctors Abs_Ts))
  1043             (K (mk_mor_Abs_tac inv inver_Abss inver_Reps))
  1044           |> Thm.close_derivation;
  1045       in
  1046         (mor_Rep, mor_Abs)
  1047       end;
  1048 
  1049     val timer = time (timer "ctor definitions & thms");
  1050 
  1051     val fold_fun = Term.absfree fold_f'
  1052       (mk_mor UNIVs ctors active_UNIVs ss (map (mk_nthN n fold_f) ks));
  1053     val foldx = HOLogic.choice_const foldT $ fold_fun;
  1054 
  1055     fun fold_bind i = Binding.suffix_name ("_" ^ ctor_foldN) (nth bs (i - 1));
  1056     val fold_name = Binding.name_of o fold_bind;
  1057     val fold_def_bind = rpair [] o Thm.def_binding o fold_bind;
  1058 
  1059     fun fold_spec i T AT =
  1060       let
  1061         val foldT = Library.foldr (op -->) (sTs, T --> AT);
  1062 
  1063         val lhs = Term.list_comb (Free (fold_name i, foldT), ss);
  1064         val rhs = mk_nthN n foldx i;
  1065       in
  1066         mk_Trueprop_eq (lhs, rhs)
  1067       end;
  1068 
  1069     val ((fold_frees, (_, fold_def_frees)), (lthy, lthy_old)) =
  1070       lthy
  1071       |> fold_map3 (fn i => fn T => fn AT =>
  1072         Specification.definition
  1073           (SOME (fold_bind i, NONE, NoSyn), (fold_def_bind i, fold_spec i T AT)))
  1074           ks Ts activeAs
  1075       |>> apsnd split_list o split_list
  1076       ||> `Local_Theory.restore;
  1077 
  1078     val phi = Proof_Context.export_morphism lthy_old lthy;
  1079     val folds = map (Morphism.term phi) fold_frees;
  1080     val fold_names = map (fst o dest_Const) folds;
  1081     fun mk_fold Ts ss i = Term.list_comb (Const (nth fold_names (i - 1), Library.foldr (op -->)
  1082       (map fastype_of ss, nth Ts (i - 1) --> range_type (fastype_of (nth ss (i - 1))))), ss);
  1083     val fold_defs = map (Morphism.thm phi) fold_def_frees;
  1084 
  1085     val mor_fold_thm =
  1086       let
  1087         val ex_mor = talg_thm RS init_ex_mor_thm;
  1088         val mor_cong = mor_cong_thm OF (map (mk_nth_conv n) ks);
  1089         val mor_comp = mor_Rep_thm RS mor_comp_thm;
  1090         val cT = certifyT lthy foldT;
  1091         val ct = certify lthy fold_fun
  1092       in
  1093         singleton (Proof_Context.export names_lthy lthy)
  1094           (Goal.prove_sorry lthy [] []
  1095             (HOLogic.mk_Trueprop (mk_mor UNIVs ctors active_UNIVs ss (map (mk_fold Ts ss) ks)))
  1096             (K (mk_mor_fold_tac cT ct fold_defs ex_mor (mor_comp RS mor_cong))))
  1097         |> Thm.close_derivation
  1098       end;
  1099 
  1100     val ctor_fold_thms = map (fn morE => rule_by_tactic lthy
  1101       ((rtac CollectI THEN' CONJ_WRAP' (K (rtac @{thm subset_UNIV})) (1 upto m + n)) 1)
  1102       (mor_fold_thm RS morE)) morE_thms;
  1103 
  1104     val (fold_unique_mor_thms, fold_unique_mor_thm) =
  1105       let
  1106         val prem = HOLogic.mk_Trueprop (mk_mor UNIVs ctors active_UNIVs ss fs);
  1107         fun mk_fun_eq f i = HOLogic.mk_eq (f, mk_fold Ts ss i);
  1108         val unique = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_fun_eq fs ks));
  1109         val unique_mor = Goal.prove_sorry lthy [] []
  1110           (fold_rev Logic.all (ss @ fs) (Logic.mk_implies (prem, unique)))
  1111           (K (mk_fold_unique_mor_tac type_defs init_unique_mor_thms Reps
  1112             mor_comp_thm mor_Abs_thm mor_fold_thm))
  1113           |> Thm.close_derivation;
  1114       in
  1115         `split_conj_thm unique_mor
  1116       end;
  1117 
  1118     val ctor_fold_unique_thms =
  1119       split_conj_thm (mk_conjIN n RS
  1120         (mor_UNIV_thm RS @{thm ssubst[of _ _ "%x. x"]} RS fold_unique_mor_thm))
  1121 
  1122     val fold_ctor_thms =
  1123       map (fn thm => (mor_incl_thm OF replicate n @{thm subset_UNIV}) RS thm RS sym)
  1124         fold_unique_mor_thms;
  1125 
  1126     val ctor_o_fold_thms =
  1127       let
  1128         val mor = mor_comp_thm OF [mor_fold_thm, mor_str_thm];
  1129       in
  1130         map2 (fn unique => fn fold_ctor =>
  1131           trans OF [mor RS unique, fold_ctor]) fold_unique_mor_thms fold_ctor_thms
  1132       end;
  1133 
  1134     val timer = time (timer "fold definitions & thms");
  1135 
  1136     val map_ctors = map2 (fn Ds => fn bnf =>
  1137       Term.list_comb (mk_map_of_bnf Ds (passiveAs @ FTs) (passiveAs @ Ts) bnf,
  1138         map HOLogic.id_const passiveAs @ ctors)) Dss bnfs;
  1139 
  1140     fun dtor_bind i = Binding.suffix_name ("_" ^ dtorN) (nth bs (i - 1));
  1141     val dtor_name = Binding.name_of o dtor_bind;
  1142     val dtor_def_bind = rpair [] o Thm.def_binding o dtor_bind;
  1143 
  1144     fun dtor_spec i FT T =
  1145       let
  1146         val dtorT = T --> FT;
  1147 
  1148         val lhs = Free (dtor_name i, dtorT);
  1149         val rhs = mk_fold Ts map_ctors i;
  1150       in
  1151         mk_Trueprop_eq (lhs, rhs)
  1152       end;
  1153 
  1154     val ((dtor_frees, (_, dtor_def_frees)), (lthy, lthy_old)) =
  1155       lthy
  1156       |> fold_map3 (fn i => fn FT => fn T =>
  1157         Specification.definition
  1158           (SOME (dtor_bind i, NONE, NoSyn), (dtor_def_bind i, dtor_spec i FT T))) ks FTs Ts
  1159       |>> apsnd split_list o split_list
  1160       ||> `Local_Theory.restore;
  1161 
  1162     val phi = Proof_Context.export_morphism lthy_old lthy;
  1163     fun mk_dtors params =
  1164       map (Term.subst_atomic_types (map (Morphism.typ phi) params' ~~ params) o Morphism.term phi)
  1165         dtor_frees;
  1166     val dtors = mk_dtors params';
  1167     val dtor_defs = map (Morphism.thm phi) dtor_def_frees;
  1168 
  1169     val ctor_o_dtor_thms = map2 (fold_thms lthy o single) dtor_defs ctor_o_fold_thms;
  1170 
  1171     val dtor_o_ctor_thms =
  1172       let
  1173         fun mk_goal dtor ctor FT =
  1174           mk_Trueprop_eq (HOLogic.mk_comp (dtor, ctor), HOLogic.id_const FT);
  1175         val goals = map3 mk_goal dtors ctors FTs;
  1176       in
  1177         map5 (fn goal => fn dtor_def => fn foldx => fn map_comp_id => fn map_cong0L =>
  1178           Goal.prove_sorry lthy [] [] goal
  1179             (K (mk_dtor_o_ctor_tac dtor_def foldx map_comp_id map_cong0L ctor_o_fold_thms))
  1180           |> Thm.close_derivation)
  1181         goals dtor_defs ctor_fold_thms map_comp_id_thms map_cong0L_thms
  1182       end;
  1183 
  1184     val dtor_ctor_thms = map (fn thm => thm RS @{thm pointfree_idE}) dtor_o_ctor_thms;
  1185     val ctor_dtor_thms = map (fn thm => thm RS @{thm pointfree_idE}) ctor_o_dtor_thms;
  1186 
  1187     val bij_dtor_thms =
  1188       map2 (fn thm1 => fn thm2 => @{thm o_bij} OF [thm1, thm2]) ctor_o_dtor_thms dtor_o_ctor_thms;
  1189     val inj_dtor_thms = map (fn thm => thm RS @{thm bij_is_inj}) bij_dtor_thms;
  1190     val surj_dtor_thms = map (fn thm => thm RS @{thm bij_is_surj}) bij_dtor_thms;
  1191     val dtor_nchotomy_thms = map (fn thm => thm RS @{thm surjD}) surj_dtor_thms;
  1192     val dtor_inject_thms = map (fn thm => thm RS @{thm inj_eq}) inj_dtor_thms;
  1193     val dtor_exhaust_thms = map (fn thm => thm RS exE) dtor_nchotomy_thms;
  1194 
  1195     val bij_ctor_thms =
  1196       map2 (fn thm1 => fn thm2 => @{thm o_bij} OF [thm1, thm2]) dtor_o_ctor_thms ctor_o_dtor_thms;
  1197     val inj_ctor_thms = map (fn thm => thm RS @{thm bij_is_inj}) bij_ctor_thms;
  1198     val surj_ctor_thms = map (fn thm => thm RS @{thm bij_is_surj}) bij_ctor_thms;
  1199     val ctor_nchotomy_thms = map (fn thm => thm RS @{thm surjD}) surj_ctor_thms;
  1200     val ctor_inject_thms = map (fn thm => thm RS @{thm inj_eq}) inj_ctor_thms;
  1201     val ctor_exhaust_thms = map (fn thm => thm RS exE) ctor_nchotomy_thms;
  1202 
  1203     val timer = time (timer "dtor definitions & thms");
  1204 
  1205     val fst_rec_pair_thms =
  1206       let
  1207         val mor = mor_comp_thm OF [mor_fold_thm, mor_convol_thm];
  1208       in
  1209         map2 (fn unique => fn fold_ctor =>
  1210           trans OF [mor RS unique, fold_ctor]) fold_unique_mor_thms fold_ctor_thms
  1211       end;
  1212 
  1213     fun rec_bind i = Binding.suffix_name ("_" ^ ctor_recN) (nth bs (i - 1));
  1214     val rec_name = Binding.name_of o rec_bind;
  1215     val rec_def_bind = rpair [] o Thm.def_binding o rec_bind;
  1216 
  1217     val rec_strs =
  1218       map3 (fn ctor => fn prod_s => fn mapx =>
  1219         mk_convol (HOLogic.mk_comp (ctor, Term.list_comb (mapx, passive_ids @ rec_fsts)), prod_s))
  1220       ctors rec_ss rec_maps;
  1221 
  1222     fun rec_spec i T AT =
  1223       let
  1224         val recT = Library.foldr (op -->) (rec_sTs, T --> AT);
  1225 
  1226         val lhs = Term.list_comb (Free (rec_name i, recT), rec_ss);
  1227         val rhs = HOLogic.mk_comp (snd_const (HOLogic.mk_prodT (T, AT)), mk_fold Ts rec_strs i);
  1228       in
  1229         mk_Trueprop_eq (lhs, rhs)
  1230       end;
  1231 
  1232     val ((rec_frees, (_, rec_def_frees)), (lthy, lthy_old)) =
  1233       lthy
  1234       |> fold_map3 (fn i => fn T => fn AT =>
  1235         Specification.definition
  1236           (SOME (rec_bind i, NONE, NoSyn), (rec_def_bind i, rec_spec i T AT)))
  1237           ks Ts activeAs
  1238       |>> apsnd split_list o split_list
  1239       ||> `Local_Theory.restore;
  1240 
  1241     val phi = Proof_Context.export_morphism lthy_old lthy;
  1242     val recs = map (Morphism.term phi) rec_frees;
  1243     val rec_names = map (fst o dest_Const) recs;
  1244     fun mk_rec ss i = Term.list_comb (Const (nth rec_names (i - 1), Library.foldr (op -->)
  1245       (map fastype_of ss, nth Ts (i - 1) --> range_type (fastype_of (nth ss (i - 1))))), ss);
  1246     val rec_defs = map (Morphism.thm phi) rec_def_frees;
  1247 
  1248     val convols = map2 (fn T => fn i => mk_convol (HOLogic.id_const T, mk_rec rec_ss i)) Ts ks;
  1249     val ctor_rec_thms =
  1250       let
  1251         fun mk_goal i rec_s rec_map ctor x =
  1252           let
  1253             val lhs = mk_rec rec_ss i $ (ctor $ x);
  1254             val rhs = rec_s $ (Term.list_comb (rec_map, passive_ids @ convols) $ x);
  1255           in
  1256             fold_rev Logic.all (x :: rec_ss) (mk_Trueprop_eq (lhs, rhs))
  1257           end;
  1258         val goals = map5 mk_goal ks rec_ss rec_maps_rev ctors xFs;
  1259       in
  1260         map2 (fn goal => fn foldx =>
  1261           Goal.prove_sorry lthy [] [] goal (mk_rec_tac rec_defs foldx fst_rec_pair_thms)
  1262           |> Thm.close_derivation)
  1263         goals ctor_fold_thms
  1264       end;
  1265 
  1266     val rec_unique_mor_thm =
  1267       let
  1268         val id_fs = map2 (fn T => fn f => mk_convol (HOLogic.id_const T, f)) Ts fs;
  1269         val prem = HOLogic.mk_Trueprop (mk_mor UNIVs ctors rec_UNIVs rec_strs id_fs);
  1270         fun mk_fun_eq f i = HOLogic.mk_eq (f, mk_rec rec_ss i);
  1271         val unique = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_fun_eq fs ks));
  1272       in
  1273         Goal.prove_sorry lthy [] []
  1274           (fold_rev Logic.all (rec_ss @ fs) (Logic.mk_implies (prem, unique)))
  1275           (mk_rec_unique_mor_tac rec_defs fst_rec_pair_thms fold_unique_mor_thm)
  1276           |> Thm.close_derivation
  1277       end;
  1278 
  1279     val ctor_rec_unique_thms =
  1280       split_conj_thm (split_conj_prems n
  1281         (mor_UNIV_thm RS @{thm ssubst[of _ _ "%x. x"]} RS rec_unique_mor_thm)
  1282         |> Local_Defs.unfold lthy (@{thms convol_o o_id id_o o_assoc[symmetric] fst_convol} @
  1283            map_ids @ sym_map_comps) OF replicate n @{thm arg_cong2[of _ _ _ _ convol, OF refl]});
  1284 
  1285     val timer = time (timer "rec definitions & thms");
  1286 
  1287     val (ctor_induct_thm, induct_params) =
  1288       let
  1289         fun mk_prem phi ctor sets x =
  1290           let
  1291             fun mk_IH phi set z =
  1292               let
  1293                 val prem = HOLogic.mk_Trueprop (HOLogic.mk_mem (z, set $ x));
  1294                 val concl = HOLogic.mk_Trueprop (phi $ z);
  1295               in
  1296                 Logic.all z (Logic.mk_implies (prem, concl))
  1297               end;
  1298 
  1299             val IHs = map3 mk_IH phis (drop m sets) Izs;
  1300             val concl = HOLogic.mk_Trueprop (phi $ (ctor $ x));
  1301           in
  1302             Logic.all x (Logic.list_implies (IHs, concl))
  1303           end;
  1304 
  1305         val prems = map4 mk_prem phis ctors FTs_setss xFs;
  1306 
  1307         fun mk_concl phi z = phi $ z;
  1308         val concl =
  1309           HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 mk_concl phis Izs));
  1310 
  1311         val goal = Logic.list_implies (prems, concl);
  1312       in
  1313         (Goal.prove_sorry lthy [] []
  1314           (fold_rev Logic.all (phis @ Izs) goal)
  1315           (K (mk_ctor_induct_tac lthy m set_map'ss init_induct_thm morE_thms mor_Abs_thm
  1316             Rep_inverses Abs_inverses Reps))
  1317         |> Thm.close_derivation,
  1318         rev (Term.add_tfrees goal []))
  1319       end;
  1320 
  1321     val cTs = map (SOME o certifyT lthy o TFree) induct_params;
  1322 
  1323     val weak_ctor_induct_thms =
  1324       let fun insts i = (replicate (i - 1) TrueI) @ (@{thm asm_rl} :: replicate (n - i) TrueI);
  1325       in map (fn i => (ctor_induct_thm OF insts i) RS mk_conjunctN n i) ks end;
  1326 
  1327     val (ctor_induct2_thm, induct2_params) =
  1328       let
  1329         fun mk_prem phi ctor ctor' sets sets' x y =
  1330           let
  1331             fun mk_IH phi set set' z1 z2 =
  1332               let
  1333                 val prem1 = HOLogic.mk_Trueprop (HOLogic.mk_mem (z1, (set $ x)));
  1334                 val prem2 = HOLogic.mk_Trueprop (HOLogic.mk_mem (z2, (set' $ y)));
  1335                 val concl = HOLogic.mk_Trueprop (phi $ z1 $ z2);
  1336               in
  1337                 fold_rev Logic.all [z1, z2] (Logic.list_implies ([prem1, prem2], concl))
  1338               end;
  1339 
  1340             val IHs = map5 mk_IH phi2s (drop m sets) (drop m sets') Izs1 Izs2;
  1341             val concl = HOLogic.mk_Trueprop (phi $ (ctor $ x) $ (ctor' $ y));
  1342           in
  1343             fold_rev Logic.all [x, y] (Logic.list_implies (IHs, concl))
  1344           end;
  1345 
  1346         val prems = map7 mk_prem phi2s ctors ctor's FTs_setss FTs'_setss xFs yFs;
  1347 
  1348         fun mk_concl phi z1 z2 = phi $ z1 $ z2;
  1349         val concl = HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1350           (map3 mk_concl phi2s Izs1 Izs2));
  1351         fun mk_t phi (z1, z1') (z2, z2') =
  1352           Term.absfree z1' (HOLogic.mk_all (fst z2', snd z2', phi $ z1 $ z2));
  1353         val cts = map3 (SOME o certify lthy ooo mk_t) phi2s (Izs1 ~~ Izs1') (Izs2 ~~ Izs2');
  1354         val goal = Logic.list_implies (prems, concl);
  1355       in
  1356         (singleton (Proof_Context.export names_lthy lthy)
  1357           (Goal.prove_sorry lthy [] [] goal
  1358             (mk_ctor_induct2_tac cTs cts ctor_induct_thm weak_ctor_induct_thms))
  1359           |> Thm.close_derivation,
  1360         rev (Term.add_tfrees goal []))
  1361       end;
  1362 
  1363     val timer = time (timer "induction");
  1364 
  1365     (*register new datatypes as BNFs*)
  1366     val (Ibnfs, folded_ctor_map_thms, folded_ctor_set_thmss', ctor_Irel_thms, lthy) =
  1367       if m = 0 then
  1368         let val dummy_thms = replicate n Drule.dummy_thm in
  1369           (replicate n DEADID_bnf, dummy_thms, replicate n [], dummy_thms, lthy)
  1370         end
  1371       else let
  1372         val fTs = map2 (curry op -->) passiveAs passiveBs;
  1373         val f1Ts = map2 (curry op -->) passiveAs passiveYs;
  1374         val f2Ts = map2 (curry op -->) passiveBs passiveYs;
  1375         val p1Ts = map2 (curry op -->) passiveXs passiveAs;
  1376         val p2Ts = map2 (curry op -->) passiveXs passiveBs;
  1377         val uTs = map2 (curry op -->) Ts Ts';
  1378         val B1Ts = map HOLogic.mk_setT passiveAs;
  1379         val B2Ts = map HOLogic.mk_setT passiveBs;
  1380         val AXTs = map HOLogic.mk_setT passiveXs;
  1381         val XTs = mk_Ts passiveXs;
  1382         val YTs = mk_Ts passiveYs;
  1383         val IRTs = map2 (curry mk_relT) passiveAs passiveBs;
  1384         val IphiTs = map2 mk_pred2T passiveAs passiveBs;
  1385 
  1386         val (((((((((((((((fs, fs'), fs_copy), us),
  1387           B1s), B2s), AXs), (xs, xs')), f1s), f2s), p1s), p2s), (ys, ys')), IRs), Iphis),
  1388           names_lthy) = names_lthy
  1389           |> mk_Frees' "f" fTs
  1390           ||>> mk_Frees "f" fTs
  1391           ||>> mk_Frees "u" uTs
  1392           ||>> mk_Frees "B1" B1Ts
  1393           ||>> mk_Frees "B2" B2Ts
  1394           ||>> mk_Frees "A" AXTs
  1395           ||>> mk_Frees' "x" XTs
  1396           ||>> mk_Frees "f1" f1Ts
  1397           ||>> mk_Frees "f2" f2Ts
  1398           ||>> mk_Frees "p1" p1Ts
  1399           ||>> mk_Frees "p2" p2Ts
  1400           ||>> mk_Frees' "y" passiveAs
  1401           ||>> mk_Frees "S" IRTs
  1402           ||>> mk_Frees "R" IphiTs;
  1403 
  1404         val map_FTFT's = map2 (fn Ds =>
  1405           mk_map_of_bnf Ds (passiveAs @ Ts) (passiveBs @ Ts')) Dss bnfs;
  1406         fun mk_passive_maps ATs BTs Ts =
  1407           map2 (fn Ds => mk_map_of_bnf Ds (ATs @ Ts) (BTs @ Ts)) Dss bnfs;
  1408         fun mk_map_fold_arg fs Ts ctor fmap =
  1409           HOLogic.mk_comp (ctor, Term.list_comb (fmap, fs @ map HOLogic.id_const Ts));
  1410         fun mk_map Ts fs Ts' ctors mk_maps =
  1411           mk_fold Ts (map2 (mk_map_fold_arg fs Ts') ctors (mk_maps Ts'));
  1412         val pmapsABT' = mk_passive_maps passiveAs passiveBs;
  1413         val fs_maps = map (mk_map Ts fs Ts' ctor's pmapsABT') ks;
  1414         val fs_copy_maps = map (mk_map Ts fs_copy Ts' ctor's pmapsABT') ks;
  1415         val Yctors = mk_ctors passiveYs;
  1416         val f1s_maps = map (mk_map Ts f1s YTs Yctors (mk_passive_maps passiveAs passiveYs)) ks;
  1417         val f2s_maps = map (mk_map Ts' f2s YTs Yctors (mk_passive_maps passiveBs passiveYs)) ks;
  1418         val p1s_maps = map (mk_map XTs p1s Ts ctors (mk_passive_maps passiveXs passiveAs)) ks;
  1419         val p2s_maps = map (mk_map XTs p2s Ts' ctor's (mk_passive_maps passiveXs passiveBs)) ks;
  1420 
  1421         val ctor_map_thms =
  1422           let
  1423             fun mk_goal fs_map map ctor ctor' = fold_rev Logic.all fs
  1424               (mk_Trueprop_eq (HOLogic.mk_comp (fs_map, ctor),
  1425                 HOLogic.mk_comp (ctor', Term.list_comb (map, fs @ fs_maps))));
  1426             val goals = map4 mk_goal fs_maps map_FTFT's ctors ctor's;
  1427             val maps =
  1428               map4 (fn goal => fn foldx => fn map_comp_id => fn map_cong0 =>
  1429                 Goal.prove_sorry lthy [] [] goal (K (mk_map_tac m n foldx map_comp_id map_cong0))
  1430                 |> Thm.close_derivation)
  1431               goals ctor_fold_thms map_comp_id_thms map_cong0s;
  1432           in
  1433             map (fn thm => thm RS @{thm pointfreeE}) maps
  1434           end;
  1435 
  1436         val (ctor_map_unique_thms, ctor_map_unique_thm) =
  1437           let
  1438             fun mk_prem u map ctor ctor' =
  1439               mk_Trueprop_eq (HOLogic.mk_comp (u, ctor),
  1440                 HOLogic.mk_comp (ctor', Term.list_comb (map, fs @ us)));
  1441             val prems = map4 mk_prem us map_FTFT's ctors ctor's;
  1442             val goal =
  1443               HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1444                 (map2 (curry HOLogic.mk_eq) us fs_maps));
  1445             val unique = Goal.prove_sorry lthy [] []
  1446               (fold_rev Logic.all (us @ fs) (Logic.list_implies (prems, goal)))
  1447               (K (mk_ctor_map_unique_tac m mor_def fold_unique_mor_thm map_comp_id_thms map_cong0s))
  1448               |> Thm.close_derivation;
  1449           in
  1450             `split_conj_thm unique
  1451           end;
  1452 
  1453         val timer = time (timer "map functions for the new datatypes");
  1454 
  1455         val bd = mk_cpow sum_bd;
  1456         val bd_Cinfinite = sum_Cinfinite RS @{thm Cinfinite_cpow};
  1457         fun mk_cpow_bd thm = @{thm ordLeq_transitive} OF
  1458           [thm, sum_Card_order RS @{thm cpow_greater_eq}];
  1459         val set_bd_cpowss = map (map mk_cpow_bd) set_bd_sumss;
  1460 
  1461         val timer = time (timer "bounds for the new datatypes");
  1462 
  1463         val ls = 1 upto m;
  1464         val setsss = map (mk_setss o mk_set_Ts) passiveAs;
  1465         val map_setss = map (fn T => map2 (fn Ds =>
  1466           mk_map_of_bnf Ds (passiveAs @ Ts) (mk_set_Ts T)) Dss bnfs) passiveAs;
  1467 
  1468         fun mk_col l T z z' sets =
  1469           let
  1470             fun mk_UN set = mk_Union T $ (set $ z);
  1471           in
  1472             Term.absfree z'
  1473               (mk_union (nth sets (l - 1) $ z,
  1474                 Library.foldl1 mk_union (map mk_UN (drop m sets))))
  1475           end;
  1476 
  1477         val colss = map5 (fn l => fn T => map3 (mk_col l T)) ls passiveAs AFss AFss' setsss;
  1478         val setss_by_range = map (fn cols => map (mk_fold Ts cols) ks) colss;
  1479         val setss_by_bnf = transpose setss_by_range;
  1480 
  1481         val ctor_set_thmss =
  1482           let
  1483             fun mk_goal sets ctor set col map =
  1484               mk_Trueprop_eq (HOLogic.mk_comp (set, ctor),
  1485                 HOLogic.mk_comp (col, Term.list_comb (map, passive_ids @ sets)));
  1486             val goalss =
  1487               map3 (fn sets => map4 (mk_goal sets) ctors sets) setss_by_range colss map_setss;
  1488             val setss = map (map2 (fn foldx => fn goal =>
  1489               Goal.prove_sorry lthy [] [] goal (K (mk_set_tac foldx)) |> Thm.close_derivation)
  1490               ctor_fold_thms) goalss;
  1491 
  1492             fun mk_simp_goal pas_set act_sets sets ctor z set =
  1493               Logic.all z (mk_Trueprop_eq (set $ (ctor $ z),
  1494                 mk_union (pas_set $ z,
  1495                   Library.foldl1 mk_union (map2 (fn X => mk_UNION (X $ z)) act_sets sets))));
  1496             val simp_goalss =
  1497               map2 (fn i => fn sets =>
  1498                 map4 (fn Fsets => mk_simp_goal (nth Fsets (i - 1)) (drop m Fsets) sets)
  1499                   FTs_setss ctors xFs sets)
  1500                 ls setss_by_range;
  1501 
  1502             val ctor_setss = map3 (fn i => map3 (fn set_nats => fn goal => fn set =>
  1503                 Goal.prove_sorry lthy [] [] goal
  1504                   (K (mk_ctor_set_tac set (nth set_nats (i - 1)) (drop m set_nats)))
  1505                 |> Thm.close_derivation)
  1506               set_map'ss) ls simp_goalss setss;
  1507           in
  1508             ctor_setss
  1509           end;
  1510 
  1511         fun mk_set_thms ctor_set = (@{thm xt1(3)} OF [ctor_set, @{thm Un_upper1}]) ::
  1512           map (fn i => (@{thm xt1(3)} OF [ctor_set, @{thm Un_upper2}]) RS
  1513             (mk_Un_upper n i RS subset_trans) RSN
  1514             (2, @{thm UN_upper} RS subset_trans))
  1515             (1 upto n);
  1516         val Fset_set_thmsss = transpose (map (map mk_set_thms) ctor_set_thmss);
  1517 
  1518         val timer = time (timer "set functions for the new datatypes");
  1519 
  1520         val cxs = map (SOME o certify lthy) Izs;
  1521         val setss_by_bnf' =
  1522           map (map (Term.subst_atomic_types (passiveAs ~~ passiveBs))) setss_by_bnf;
  1523         val setss_by_range' = transpose setss_by_bnf';
  1524 
  1525         val set_map_thmss =
  1526           let
  1527             fun mk_set_map f map z set set' =
  1528               HOLogic.mk_eq (mk_image f $ (set $ z), set' $ (map $ z));
  1529 
  1530             fun mk_cphi f map z set set' = certify lthy
  1531               (Term.absfree (dest_Free z) (mk_set_map f map z set set'));
  1532 
  1533             val csetss = map (map (certify lthy)) setss_by_range';
  1534 
  1535             val cphiss = map3 (fn f => fn sets => fn sets' =>
  1536               (map4 (mk_cphi f) fs_maps Izs sets sets')) fs setss_by_range setss_by_range';
  1537 
  1538             val inducts = map (fn cphis =>
  1539               Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm) cphiss;
  1540 
  1541             val goals =
  1542               map3 (fn f => fn sets => fn sets' =>
  1543                 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1544                   (map4 (mk_set_map f) fs_maps Izs sets sets')))
  1545                   fs setss_by_range setss_by_range';
  1546 
  1547             fun mk_tac induct = mk_set_nat_tac m (rtac induct) set_map'ss ctor_map_thms;
  1548             val thms =
  1549               map5 (fn goal => fn csets => fn ctor_sets => fn induct => fn i =>
  1550                 singleton (Proof_Context.export names_lthy lthy)
  1551                   (Goal.prove_sorry lthy [] [] goal (mk_tac induct csets ctor_sets i))
  1552                 |> Thm.close_derivation)
  1553               goals csetss ctor_set_thmss inducts ls;
  1554           in
  1555             map split_conj_thm thms
  1556           end;
  1557 
  1558         val set_bd_thmss =
  1559           let
  1560             fun mk_set_bd z set = mk_ordLeq (mk_card_of (set $ z)) bd;
  1561 
  1562             fun mk_cphi z set = certify lthy (Term.absfree (dest_Free z) (mk_set_bd z set));
  1563 
  1564             val cphiss = map (map2 mk_cphi Izs) setss_by_range;
  1565 
  1566             val inducts = map (fn cphis =>
  1567               Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm) cphiss;
  1568 
  1569             val goals =
  1570               map (fn sets =>
  1571                 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1572                   (map2 mk_set_bd Izs sets))) setss_by_range;
  1573 
  1574             fun mk_tac induct = mk_set_bd_tac m (rtac induct) bd_Cinfinite set_bd_cpowss;
  1575             val thms =
  1576               map4 (fn goal => fn ctor_sets => fn induct => fn i =>
  1577                 singleton (Proof_Context.export names_lthy lthy)
  1578                   (Goal.prove_sorry lthy [] [] goal (mk_tac induct ctor_sets i))
  1579                 |> Thm.close_derivation)
  1580               goals ctor_set_thmss inducts ls;
  1581           in
  1582             map split_conj_thm thms
  1583           end;
  1584 
  1585         val map_cong0_thms =
  1586           let
  1587             fun mk_prem z set f g y y' =
  1588               mk_Ball (set $ z) (Term.absfree y' (HOLogic.mk_eq (f $ y, g $ y)));
  1589 
  1590             fun mk_map_cong0 sets z fmap gmap =
  1591               HOLogic.mk_imp
  1592                 (Library.foldr1 HOLogic.mk_conj (map5 (mk_prem z) sets fs fs_copy ys ys'),
  1593                 HOLogic.mk_eq (fmap $ z, gmap $ z));
  1594 
  1595             fun mk_cphi sets z fmap gmap =
  1596               certify lthy (Term.absfree (dest_Free z) (mk_map_cong0 sets z fmap gmap));
  1597 
  1598             val cphis = map4 mk_cphi setss_by_bnf Izs fs_maps fs_copy_maps;
  1599 
  1600             val induct = Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm;
  1601 
  1602             val goal =
  1603               HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1604                 (map4 mk_map_cong0 setss_by_bnf Izs fs_maps fs_copy_maps));
  1605 
  1606             val thm = singleton (Proof_Context.export names_lthy lthy)
  1607               (Goal.prove_sorry lthy [] [] goal
  1608               (mk_mcong_tac (rtac induct) Fset_set_thmsss map_cong0s ctor_map_thms))
  1609               |> Thm.close_derivation;
  1610           in
  1611             split_conj_thm thm
  1612           end;
  1613 
  1614         val in_incl_min_alg_thms =
  1615           let
  1616             fun mk_prem z sets =
  1617               HOLogic.mk_mem (z, mk_in As sets (fastype_of z));
  1618 
  1619             fun mk_incl z sets i =
  1620               HOLogic.mk_imp (mk_prem z sets, HOLogic.mk_mem (z, mk_min_alg As ctors i));
  1621 
  1622             fun mk_cphi z sets i =
  1623               certify lthy (Term.absfree (dest_Free z) (mk_incl z sets i));
  1624 
  1625             val cphis = map3 mk_cphi Izs setss_by_bnf ks;
  1626 
  1627             val induct = Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct_thm;
  1628 
  1629             val goal =
  1630               HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
  1631                 (map3 mk_incl Izs setss_by_bnf ks));
  1632 
  1633             val thm = singleton (Proof_Context.export names_lthy lthy)
  1634               (Goal.prove_sorry lthy [] [] goal
  1635               (mk_incl_min_alg_tac (rtac induct) Fset_set_thmsss alg_set_thms alg_min_alg_thm))
  1636               |> Thm.close_derivation;
  1637           in
  1638             split_conj_thm thm
  1639           end;
  1640 
  1641         val Xsetss = map (map (Term.subst_atomic_types (passiveAs ~~ passiveXs))) setss_by_bnf;
  1642 
  1643         val map_wpull_thms =
  1644           let
  1645             val cTs = map (SOME o certifyT lthy o TFree) induct2_params;
  1646             val cxs = map (SOME o certify lthy) (splice Izs1 Izs2);
  1647 
  1648             fun mk_prem z1 z2 sets1 sets2 map1 map2 =
  1649               HOLogic.mk_conj
  1650                 (HOLogic.mk_mem (z1, mk_in B1s sets1 (fastype_of z1)),
  1651                 HOLogic.mk_conj
  1652                   (HOLogic.mk_mem (z2, mk_in B2s sets2 (fastype_of z2)),
  1653                   HOLogic.mk_eq (map1 $ z1, map2 $ z2)));
  1654 
  1655             val prems = map6 mk_prem Izs1 Izs2 setss_by_bnf setss_by_bnf' f1s_maps f2s_maps;
  1656 
  1657             fun mk_concl z1 z2 sets map1 map2 T x x' =
  1658               mk_Bex (mk_in AXs sets T) (Term.absfree x'
  1659                 (HOLogic.mk_conj (HOLogic.mk_eq (map1 $ x, z1), HOLogic.mk_eq (map2 $ x, z2))));
  1660 
  1661             val concls = map8 mk_concl Izs1 Izs2 Xsetss p1s_maps p2s_maps XTs xs xs';
  1662 
  1663             val goals = map2 (curry HOLogic.mk_imp) prems concls;
  1664 
  1665             fun mk_cphi z1 z2 goal = certify lthy (Term.absfree z1 (Term.absfree z2 goal));
  1666 
  1667             val cphis = map3 mk_cphi Izs1' Izs2' goals;
  1668 
  1669             val induct = Drule.instantiate' cTs (map SOME cphis @ cxs) ctor_induct2_thm;
  1670 
  1671             val goal = Logic.list_implies (map HOLogic.mk_Trueprop
  1672                 (map8 mk_wpull AXs B1s B2s f1s f2s (replicate m NONE) p1s p2s),
  1673               HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj goals));
  1674 
  1675             val thm = singleton (Proof_Context.export names_lthy lthy)
  1676               (Goal.prove_sorry lthy [] [] goal
  1677               (K (mk_lfp_map_wpull_tac lthy m (rtac induct) map_wpulls ctor_map_thms
  1678                 (transpose ctor_set_thmss) Fset_set_thmsss ctor_inject_thms)))
  1679               |> Thm.close_derivation;
  1680           in
  1681             split_conj_thm thm
  1682           end;
  1683 
  1684         val timer = time (timer "helpers for BNF properties");
  1685 
  1686         val map_id_tacs = map (K o mk_map_id_tac map_ids) ctor_map_unique_thms;
  1687         val map_comp_tacs =
  1688           map2 (K oo mk_map_comp_tac map_comp's ctor_map_thms) ctor_map_unique_thms ks;
  1689         val map_cong0_tacs = map (mk_map_cong0_tac m) map_cong0_thms;
  1690         val set_nat_tacss = map (map (K o mk_set_map_tac)) (transpose set_map_thmss);
  1691         val bd_co_tacs = replicate n (K (mk_bd_card_order_tac bd_card_orders));
  1692         val bd_cinf_tacs = replicate n (K (rtac (bd_Cinfinite RS conjunct1) 1));
  1693         val set_bd_tacss = map (map (fn thm => K (rtac thm 1))) (transpose set_bd_thmss);
  1694         val in_bd_tacs = map2 (K oo mk_in_bd_tac sum_Card_order suc_bd_Cnotzero)
  1695           in_incl_min_alg_thms card_of_min_alg_thms;
  1696         val map_wpull_tacs = map (K o mk_wpull_tac) map_wpull_thms;
  1697 
  1698         val srel_O_Gr_tacs = replicate n (simple_srel_O_Gr_tac o #context);
  1699 
  1700         val tacss = map10 zip_axioms map_id_tacs map_comp_tacs map_cong0_tacs set_nat_tacss
  1701           bd_co_tacs bd_cinf_tacs set_bd_tacss in_bd_tacs map_wpull_tacs srel_O_Gr_tacs;
  1702 
  1703         val ctor_witss =
  1704           let
  1705             val witss = map2 (fn Ds => fn bnf => mk_wits_of_bnf
  1706               (replicate (nwits_of_bnf bnf) Ds)
  1707               (replicate (nwits_of_bnf bnf) (passiveAs @ Ts)) bnf) Dss bnfs;
  1708             fun close_wit (I, wit) = fold_rev Term.absfree (map (nth ys') I) wit;
  1709             fun wit_apply (arg_I, arg_wit) (fun_I, fun_wit) =
  1710               (union (op =) arg_I fun_I, fun_wit $ arg_wit);
  1711 
  1712             fun gen_arg support i =
  1713               if i < m then [([i], nth ys i)]
  1714               else maps (mk_wit support (nth ctors (i - m)) (i - m)) (nth support (i - m))
  1715             and mk_wit support ctor i (I, wit) =
  1716               let val args = map (gen_arg (nth_map i (remove (op =) (I, wit)) support)) I;
  1717               in
  1718                 (args, [([], wit)])
  1719                 |-> fold (map_product wit_apply)
  1720                 |> map (apsnd (fn t => ctor $ t))
  1721                 |> minimize_wits
  1722               end;
  1723           in
  1724             map3 (fn ctor => fn i => map close_wit o minimize_wits o maps (mk_wit witss ctor i))
  1725               ctors (0 upto n - 1) witss
  1726           end;
  1727 
  1728         fun wit_tac ctxt _ = mk_wit_tac ctxt n (flat ctor_set_thmss) (maps wit_thms_of_bnf bnfs);
  1729 
  1730         val (Ibnfs, lthy) =
  1731           fold_map9 (fn tacs => fn b => fn map_b => fn rel_b => fn set_bs => fn mapx => fn sets =>
  1732               fn T => fn wits => fn lthy =>
  1733             bnf_def Dont_Inline (user_policy Note_Some) I tacs (wit_tac lthy) (SOME deads)
  1734               map_b rel_b set_bs
  1735               (((((b, fold_rev Term.absfree fs' mapx), sets), absdummy T bd), wits), NONE)
  1736               lthy
  1737             |> register_bnf (Local_Theory.full_name lthy b))
  1738           tacss bs map_bs rel_bs set_bss fs_maps setss_by_bnf Ts ctor_witss lthy;
  1739 
  1740         val fold_maps = fold_thms lthy (map (fn bnf =>
  1741           mk_unabs_def m (map_def_of_bnf bnf RS meta_eq_to_obj_eq)) Ibnfs);
  1742 
  1743         val fold_sets = fold_thms lthy (maps (fn bnf =>
  1744           map (fn thm => thm RS meta_eq_to_obj_eq) (set_defs_of_bnf bnf)) Ibnfs);
  1745 
  1746         val timer = time (timer "registered new datatypes as BNFs");
  1747 
  1748         val srels = map2 (fn Ds => mk_srel_of_bnf Ds (passiveAs @ Ts) (passiveBs @ Ts')) Dss bnfs;
  1749         val Isrels = map (mk_srel_of_bnf deads passiveAs passiveBs) Ibnfs;
  1750         val rels = map2 (fn Ds => mk_rel_of_bnf Ds (passiveAs @ Ts) (passiveBs @ Ts')) Dss bnfs;
  1751         val Irels = map (mk_rel_of_bnf deads passiveAs passiveBs) Ibnfs;
  1752 
  1753         val IsrelRs = map (fn Isrel => Term.list_comb (Isrel, IRs)) Isrels;
  1754         val srelRs = map (fn srel => Term.list_comb (srel, IRs @ IsrelRs)) srels;
  1755         val Irelphis = map (fn Isrel => Term.list_comb (Isrel, Iphis)) Irels;
  1756         val relphis = map (fn srel => Term.list_comb (srel, Iphis @ Irelphis)) rels;
  1757 
  1758         val in_srels = map in_srel_of_bnf bnfs;
  1759         val in_Isrels = map in_srel_of_bnf Ibnfs;
  1760         val srel_defs = map srel_def_of_bnf bnfs;
  1761         val Isrel_defs = map srel_def_of_bnf Ibnfs;
  1762         val Irel_defs = map rel_def_of_bnf Ibnfs;
  1763 
  1764         val ctor_set_incl_thmss = map (map (fold_sets o hd)) Fset_set_thmsss;
  1765         val ctor_set_set_incl_thmsss = map (transpose o map (map fold_sets o tl)) Fset_set_thmsss;
  1766         val folded_ctor_map_thms = map fold_maps ctor_map_thms;
  1767         val folded_ctor_set_thmss = map (map fold_sets) ctor_set_thmss;
  1768         val folded_ctor_set_thmss' = transpose folded_ctor_set_thmss;
  1769 
  1770         val ctor_Isrel_thms =
  1771           let
  1772             fun mk_goal xF yF ctor ctor' IsrelR srelR = fold_rev Logic.all (xF :: yF :: IRs)
  1773               (mk_Trueprop_eq (HOLogic.mk_mem (HOLogic.mk_prod (ctor $ xF, ctor' $ yF), IsrelR),
  1774                   HOLogic.mk_mem (HOLogic.mk_prod (xF, yF), srelR)));
  1775             val goals = map6 mk_goal xFs yFs ctors ctor's IsrelRs srelRs;
  1776           in
  1777             map12 (fn i => fn goal => fn in_srel => fn map_comp => fn map_cong0 =>
  1778               fn ctor_map => fn ctor_sets => fn ctor_inject => fn ctor_dtor =>
  1779               fn set_maps => fn ctor_set_incls => fn ctor_set_set_inclss =>
  1780               Goal.prove_sorry lthy [] [] goal
  1781                (K (mk_ctor_srel_tac lthy in_Isrels i in_srel map_comp map_cong0 ctor_map ctor_sets
  1782                  ctor_inject ctor_dtor set_maps ctor_set_incls ctor_set_set_inclss))
  1783               |> Thm.close_derivation)
  1784             ks goals in_srels map_comp's map_cong0s folded_ctor_map_thms folded_ctor_set_thmss'
  1785               ctor_inject_thms ctor_dtor_thms set_map'ss ctor_set_incl_thmss
  1786               ctor_set_set_incl_thmsss
  1787           end;
  1788 
  1789         val ctor_Irel_thms =
  1790           let
  1791             fun mk_goal xF yF ctor ctor' Ipredphi predphi = fold_rev Logic.all (xF :: yF :: Iphis)
  1792               (mk_Trueprop_eq (Ipredphi $ (ctor $ xF) $ (ctor' $ yF), predphi $ xF $ yF));
  1793             val goals = map6 mk_goal xFs yFs ctors ctor's Irelphis relphis;
  1794           in
  1795             map3 (fn goal => fn srel_def => fn ctor_Isrel =>
  1796               Goal.prove_sorry lthy [] [] goal
  1797                 (mk_ctor_or_dtor_rel_tac srel_def Irel_defs Isrel_defs ctor_Isrel)
  1798               |> Thm.close_derivation)
  1799             goals srel_defs ctor_Isrel_thms
  1800           end;
  1801 
  1802         val timer = time (timer "additional properties");
  1803 
  1804         val ls' = if m = 1 then [0] else ls
  1805 
  1806         val Ibnf_common_notes =
  1807           [(ctor_map_uniqueN, [fold_maps ctor_map_unique_thm])]
  1808           |> map (fn (thmN, thms) =>
  1809             ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]));
  1810 
  1811         val Ibnf_notes =
  1812           [(ctor_mapN, map single folded_ctor_map_thms),
  1813           (ctor_relN, map single ctor_Irel_thms),
  1814           (ctor_set_inclN, ctor_set_incl_thmss),
  1815           (ctor_set_set_inclN, map flat ctor_set_set_incl_thmsss)] @
  1816           (if note_all then
  1817              [(ctor_srelN, map single ctor_Isrel_thms)]
  1818            else
  1819              []) @
  1820           map2 (fn i => fn thms => (mk_ctor_setN i, map single thms)) ls' folded_ctor_set_thmss
  1821           |> maps (fn (thmN, thmss) =>
  1822             map2 (fn b => fn thms =>
  1823               ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]))
  1824             bs thmss)
  1825       in
  1826         timer; (Ibnfs, folded_ctor_map_thms, folded_ctor_set_thmss', ctor_Irel_thms,
  1827           lthy |> Local_Theory.notes (Ibnf_common_notes @ Ibnf_notes) |> snd)
  1828       end;
  1829 
  1830       val common_notes =
  1831         [(ctor_inductN, [ctor_induct_thm]),
  1832         (ctor_induct2N, [ctor_induct2_thm])]
  1833         |> map (fn (thmN, thms) =>
  1834           ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]));
  1835 
  1836       val notes =
  1837         [(ctor_dtorN, ctor_dtor_thms),
  1838         (ctor_exhaustN, ctor_exhaust_thms),
  1839         (ctor_foldN, ctor_fold_thms),
  1840         (ctor_fold_uniqueN, ctor_fold_unique_thms),
  1841         (ctor_rec_uniqueN, ctor_rec_unique_thms),
  1842         (ctor_injectN, ctor_inject_thms),
  1843         (ctor_recN, ctor_rec_thms),
  1844         (dtor_ctorN, dtor_ctor_thms),
  1845         (dtor_exhaustN, dtor_exhaust_thms),
  1846         (dtor_injectN, dtor_inject_thms)]
  1847         |> map (apsnd (map single))
  1848         |> maps (fn (thmN, thmss) =>
  1849           map2 (fn b => fn thms =>
  1850             ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), [(thms, [])]))
  1851           bs thmss)
  1852   in
  1853     ({Ts = Ts, bnfs = Ibnfs, ctors = ctors, dtors = dtors, un_folds = folds, co_recs = recs,
  1854       co_induct = ctor_induct_thm, strong_co_induct = ctor_induct_thm, dtor_ctors = dtor_ctor_thms,
  1855       ctor_dtors = ctor_dtor_thms, ctor_injects = ctor_inject_thms, map_thms = folded_ctor_map_thms,
  1856       set_thmss = folded_ctor_set_thmss', rel_thms = ctor_Irel_thms, un_fold_thms = ctor_fold_thms,
  1857       co_rec_thms = ctor_rec_thms},
  1858      lthy |> Local_Theory.notes (common_notes @ notes) |> snd)
  1859   end;
  1860 
  1861 val _ =
  1862   Outer_Syntax.local_theory @{command_spec "datatype_new"} "define BNF-based inductive datatypes"
  1863     (parse_co_datatype_cmd true construct_lfp);
  1864 
  1865 end;