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