src/HOL/BNF/Tools/bnf_fp_sugar.ML
changeset 49591 91b228e26348
parent 49590 43e2d0e10876
child 49592 b859a02c1150
equal deleted inserted replaced
49590:43e2d0e10876 49591:91b228e26348
     7 
     7 
     8 signature BNF_FP_SUGAR =
     8 signature BNF_FP_SUGAR =
     9 sig
     9 sig
    10   val datatypes: bool ->
    10   val datatypes: bool ->
    11     (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list ->
    11     (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list ->
    12       BNF_Def.BNF list -> local_theory ->
    12       BNF_Def.BNF list -> local_theory -> BNF_FP.fp_result * local_theory) ->
    13       (BNF_Def.BNF list * term list * term list * term list * term list * thm * thm list *
       
    14          thm list * thm list * thm list * thm list list * thm list * thm list * thm list) *
       
    15       local_theory) ->
       
    16     bool * ((((typ * sort) list * binding) * mixfix) * ((((binding * binding) *
    13     bool * ((((typ * sort) list * binding) * mixfix) * ((((binding * binding) *
    17       (binding * typ) list) * (binding * term) list) * mixfix) list) list ->
    14       (binding * typ) list) * (binding * term) list) * mixfix) list) list ->
    18     local_theory -> local_theory
    15     local_theory -> local_theory
    19   val parse_datatype_cmd: bool ->
    16   val parse_datatype_cmd: bool ->
    20     (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list ->
    17     (mixfix list -> (string * sort) list option -> binding list -> typ list * typ list list ->
    21       BNF_Def.BNF list -> local_theory ->
    18       BNF_Def.BNF list -> local_theory -> BNF_FP.fp_result * local_theory) ->
    22       (BNF_Def.BNF list * term list * term list * term list * term list * thm * thm list *
       
    23          thm list * thm list * thm list * thm list list * thm list * thm list * thm list) *
       
    24       local_theory) ->
       
    25     (local_theory -> local_theory) parser
    19     (local_theory -> local_theory) parser
    26 end;
    20 end;
    27 
    21 
    28 structure BNF_FP_Sugar : BNF_FP_SUGAR =
    22 structure BNF_FP_Sugar : BNF_FP_SUGAR =
    29 struct
    23 struct
    31 open BNF_Util
    25 open BNF_Util
    32 open BNF_Wrap
    26 open BNF_Wrap
    33 open BNF_Def
    27 open BNF_Def
    34 open BNF_FP
    28 open BNF_FP
    35 open BNF_FP_Sugar_Tactics
    29 open BNF_FP_Sugar_Tactics
       
    30 
       
    31 val mp_conj = @{thm mp_conj};
    36 
    32 
    37 val simp_attrs = @{attributes [simp]};
    33 val simp_attrs = @{attributes [simp]};
    38 val code_simp_attrs = Code.add_default_eqn_attrib :: simp_attrs;
    34 val code_simp_attrs = Code.add_default_eqn_attrib :: simp_attrs;
    39 
    35 
    40 fun split_list4 xs = (map #1 xs, map #2 xs, map #3 xs, map #4 xs);
    36 fun split_list4 xs = (map #1 xs, map #2 xs, map #3 xs, map #4 xs);
    94 fun mk_map live Ts Us t =
    90 fun mk_map live Ts Us t =
    95   let val (Type (_, Ts0), Type (_, Us0)) = strip_typeN (live + 1) (fastype_of t) |>> List.last in
    91   let val (Type (_, Ts0), Type (_, Us0)) = strip_typeN (live + 1) (fastype_of t) |>> List.last in
    96     Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t
    92     Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t
    97   end;
    93   end;
    98 
    94 
       
    95 fun mk_rel live Ts Us t =
       
    96   let val [Type (_, Ts0), Type (_, Us0)] = binder_types (snd (strip_typeN live (fastype_of t))) in
       
    97     Term.subst_atomic_types (Ts0 @ Us0 ~~ Ts @ Us) t
       
    98   end;
       
    99 
    99 fun liveness_of_fp_bnf n bnf =
   100 fun liveness_of_fp_bnf n bnf =
   100   (case T_of_bnf bnf of
   101   (case T_of_bnf bnf of
   101     Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts
   102     Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts
   102   | _ => replicate n false);
   103   | _ => replicate n false);
   103 
   104 
   116   if length As = length As' then map2 merge_type_arg As As' else cannot_merge_types ();
   117   if length As = length As' then map2 merge_type_arg As As' else cannot_merge_types ();
   117 
   118 
   118 fun is_triv_implies thm =
   119 fun is_triv_implies thm =
   119   op aconv (Logic.dest_implies (Thm.prop_of thm))
   120   op aconv (Logic.dest_implies (Thm.prop_of thm))
   120   handle TERM _ => false;
   121   handle TERM _ => false;
       
   122 
       
   123 fun reassoc_conjs thm =
       
   124   reassoc_conjs (thm RS @{thm conj_assoc[THEN iffD1]})
       
   125   handle THM _ => thm;
   121 
   126 
   122 fun type_args_constrained_of (((cAs, _), _), _) = cAs;
   127 fun type_args_constrained_of (((cAs, _), _), _) = cAs;
   123 fun type_binding_of (((_, b), _), _) = b;
   128 fun type_binding_of (((_, b), _), _) = b;
   124 fun mixfix_of ((_, mx), _) = mx;
   129 fun mixfix_of ((_, mx), _) = mx;
   125 fun ctr_specs_of (_, ctr_specs) = ctr_specs;
   130 fun ctr_specs_of (_, ctr_specs) = ctr_specs;
   203     val _ = (case subtract (op =) (map dest_TFree As) rhs_As' of
   208     val _ = (case subtract (op =) (map dest_TFree As) rhs_As' of
   204         [] => ()
   209         [] => ()
   205       | A' :: _ => error ("Extra type variable on right-hand side: " ^
   210       | A' :: _ => error ("Extra type variable on right-hand side: " ^
   206           quote (Syntax.string_of_typ no_defs_lthy (TFree A'))));
   211           quote (Syntax.string_of_typ no_defs_lthy (TFree A'))));
   207 
   212 
   208     fun eq_fpT (T as Type (s, Us)) (Type (s', Us')) =
   213     fun eq_fpT_check (T as Type (s, Us)) (Type (s', Us')) =
   209         s = s' andalso (Us = Us' orelse error ("Illegal occurrence of recursive type " ^
   214         s = s' andalso (Us = Us' orelse error ("Illegal occurrence of recursive type " ^
   210           quote (Syntax.string_of_typ fake_lthy T)))
   215           quote (Syntax.string_of_typ fake_lthy T)))
   211       | eq_fpT _ _ = false;
   216       | eq_fpT_check _ _ = false;
   212 
   217 
   213     fun freeze_fp (T as Type (s, Us)) =
   218     fun freeze_fp (T as Type (s, Us)) =
   214         (case find_index (eq_fpT T) fake_Ts of ~1 => Type (s, map freeze_fp Us) | j => nth Xs j)
   219         (case find_index (eq_fpT_check T) fake_Ts of
       
   220           ~1 => Type (s, map freeze_fp Us)
       
   221         | kk => nth Xs kk)
   215       | freeze_fp T = T;
   222       | freeze_fp T = T;
   216 
   223 
   217     val ctr_TsssXs = map (map (map freeze_fp)) fake_ctr_Tsss;
   224     val ctr_TsssXs = map (map (map freeze_fp)) fake_ctr_Tsss;
   218     val ctr_sum_prod_TsXs = map (mk_sumTN_balanced o map HOLogic.mk_tupleT) ctr_TsssXs;
   225     val ctr_sum_prod_TsXs = map (mk_sumTN_balanced o map HOLogic.mk_tupleT) ctr_TsssXs;
   219 
   226 
   220     val fp_eqs =
   227     val fp_eqs =
   221       map dest_TFree Xs ~~ map (Term.typ_subst_atomic (As ~~ unsorted_As)) ctr_sum_prod_TsXs;
   228       map dest_TFree Xs ~~ map (Term.typ_subst_atomic (As ~~ unsorted_As)) ctr_sum_prod_TsXs;
   222 
   229 
   223     (* TODO: clean up list *)
   230     (* TODO: clean up list *)
   224     val (pre_bnfs, ((fp_bnfs as any_fp_bnf :: _, dtors0, ctors0, fp_folds0, fp_recs0, fp_induct,
   231     val (pre_bnfs, ((fp_bnfs as any_fp_bnf :: _, dtors0, ctors0, fp_folds0, fp_recs0, fp_induct,
   225            dtor_ctors, ctor_dtors, ctor_injects, fp_map_thms, fp_set_thmss, fp_rel_thms,
   232            fp_strong_induct, dtor_ctors, ctor_dtors, ctor_injects, fp_map_thms, fp_set_thmss,
   226            fp_fold_thms, fp_rec_thms), lthy)) =
   233            fp_rel_thms, fp_fold_thms, fp_rec_thms), lthy)) =
   227       fp_bnf construct_fp fp_bs mixfixes (map dest_TFree unsorted_As) fp_eqs no_defs_lthy0;
   234       fp_bnf construct_fp fp_bs mixfixes (map dest_TFree unsorted_As) fp_eqs no_defs_lthy0;
   228 
   235 
   229     val timer = time (Timer.startRealTimer ());
   236     val timer = time (Timer.startRealTimer ());
   230 
   237 
   231     fun add_nesty_bnf_names Us =
   238     fun add_nesty_bnf_names Us =
   245 
   252 
   246     val pre_map_defs = map map_def_of_bnf pre_bnfs;
   253     val pre_map_defs = map map_def_of_bnf pre_bnfs;
   247     val pre_set_defss = map set_defs_of_bnf pre_bnfs;
   254     val pre_set_defss = map set_defs_of_bnf pre_bnfs;
   248     val pre_rel_defs = map rel_def_of_bnf pre_bnfs;
   255     val pre_rel_defs = map rel_def_of_bnf pre_bnfs;
   249     val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs;
   256     val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs;
       
   257     val nesting_map_ids = map map_id_of_bnf nesting_bnfs;
   250     val nesting_set_natural's = maps set_natural'_of_bnf nesting_bnfs;
   258     val nesting_set_natural's = maps set_natural'_of_bnf nesting_bnfs;
   251     val nesting_map_ids = map map_id_of_bnf nesting_bnfs;
       
   252 
   259 
   253     val live = live_of_bnf any_fp_bnf;
   260     val live = live_of_bnf any_fp_bnf;
   254 
   261 
   255     val Bs =
   262     val Bs =
   256       map3 (fn alive => fn A as TFree (_, S) => fn B => if alive then resort_tfree S B else A)
   263       map3 (fn alive => fn A as TFree (_, S) => fn B => if alive then resort_tfree S B else A)
   277     val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold)));
   284     val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold)));
   278     val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec)));
   285     val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec)));
   279 
   286 
   280     val (((fold_only as (gss, _, _), rec_only as (hss, _, _)),
   287     val (((fold_only as (gss, _, _), rec_only as (hss, _, _)),
   281           (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))),
   288           (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))),
   282          names_lthy) =
   289          names_lthy0) =
   283       if lfp then
   290       if lfp then
   284         let
   291         let
   285           val y_Tsss =
   292           val y_Tsss =
   286             map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type)
   293             map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type)
   287               ns mss fp_fold_fun_Ts;
   294               ns mss fp_fold_fun_Ts;
   518 
   525 
   519             val rel_infos = (ctr_defs' ~~ xss ~~ cxIns, ctr_defs' ~~ yss ~~ cyIns);
   526             val rel_infos = (ctr_defs' ~~ xss ~~ cxIns, ctr_defs' ~~ yss ~~ cyIns);
   520 
   527 
   521             fun mk_rel_thm postproc ctr_defs' xs cxIn ys cyIn =
   528             fun mk_rel_thm postproc ctr_defs' xs cxIn ys cyIn =
   522               fold_thms lthy ctr_defs'
   529               fold_thms lthy ctr_defs'
   523                  (unfold_thms lthy (pre_rel_def ::
   530                  (unfold_thms lthy (pre_rel_def :: (if lfp then [] else [dtor_ctor]) @
   524                       (if lfp then [] else [dtor_ctor]) @ sum_prod_thms_rel)
   531                       sum_prod_thms_rel)
   525                     (cterm_instantiate_pos (nones @ [SOME cxIn, SOME cyIn]) fp_rel_thm))
   532                     (cterm_instantiate_pos (nones @ [SOME cxIn, SOME cyIn]) fp_rel_thm))
   526               |> postproc |> thaw (xs @ ys);
   533               |> postproc |> thaw (xs @ ys);
   527 
   534 
   528             fun mk_pos_rel_thm (((ctr_def', xs), cxIn), ((_, ys), cyIn)) =
   535             fun mk_pos_rel_thm (((ctr_def', xs), cxIn), ((_, ys), cyIn)) =
   529               mk_rel_thm (perhaps (try (fn th => th RS @{thm eq_sym_Unity_imp}))) [ctr_def']
   536               mk_rel_thm (unfold_thms lthy @{thms eq_sym_Unity_conv}) [ctr_def'] xs cxIn ys cyIn;
   530                 xs cxIn ys cyIn;
       
   531 
   537 
   532             val pos_rel_thms = map mk_pos_rel_thm (op ~~ rel_infos);
   538             val pos_rel_thms = map mk_pos_rel_thm (op ~~ rel_infos);
   533 
   539 
   534             fun mk_half_neg_rel_thm (((xctr_def', xs), cxIn), ((yctr_def', ys), cyIn)) =
   540             fun mk_half_neg_rel_thm (((xctr_def', xs), cxIn), ((yctr_def', ys), cyIn)) =
   535               mk_rel_thm (fn thm => thm RS @{thm eq_False[THEN iffD1]}) [xctr_def', yctr_def']
   541               mk_rel_thm (fn thm => thm RS @{thm eq_False[THEN iffD1]}) [xctr_def', yctr_def']
   645     fun build_map build_arg (Type (s, Ts)) (Type (_, Us)) =
   651     fun build_map build_arg (Type (s, Ts)) (Type (_, Us)) =
   646       let
   652       let
   647         val bnf = the (bnf_of lthy s);
   653         val bnf = the (bnf_of lthy s);
   648         val live = live_of_bnf bnf;
   654         val live = live_of_bnf bnf;
   649         val mapx = mk_map live Ts Us (map_of_bnf bnf);
   655         val mapx = mk_map live Ts Us (map_of_bnf bnf);
   650         val TUs = map dest_funT (fst (strip_typeN live (fastype_of mapx)));
   656         val TUs' = map dest_funT (fst (strip_typeN live (fastype_of mapx)));
   651         val args = map build_arg TUs;
   657       in Term.list_comb (mapx, map build_arg TUs') end;
   652       in Term.list_comb (mapx, args) end;
       
   653 
   658 
   654     (* TODO: Add map, sets, rel simps *)
   659     (* TODO: Add map, sets, rel simps *)
   655     val mk_simp_thmss =
   660     val mk_simp_thmss =
   656       map3 (fn (_, _, injects, distincts, cases, _, _, _) => fn rec_likes => fn fold_likes =>
   661       map3 (fn (_, _, _, injects, distincts, cases, _, _, _) => fn rec_likes => fn fold_likes =>
   657         injects @ distincts @ cases @ rec_likes @ fold_likes);
   662         injects @ distincts @ cases @ rec_likes @ fold_likes);
   658 
   663 
   659     fun derive_induct_fold_rec_thms_for_types (((ctrss, xsss, ctr_defss, wrap_ress), (folds, recs,
   664     fun derive_induct_fold_rec_thms_for_types (((ctrss, xsss, ctr_defss, wrap_ress), (folds, recs,
   660         fold_defs, rec_defs)), lthy) =
   665         fold_defs, rec_defs)), lthy) =
   661       let
   666       let
   662         val (((phis, phis'), us'), names_lthy) =
   667         val (((ps, ps'), us'), names_lthy) =
   663           lthy
   668           lthy
   664           |> mk_Frees' "P" (map mk_pred1T fpTs)
   669           |> mk_Frees' "P" (map mk_pred1T fpTs)
   665           ||>> Variable.variant_fixes fp_b_names;
   670           ||>> Variable.variant_fixes fp_b_names;
   666 
   671 
   667         val us = map2 (curry Free) us' fpTs;
   672         val us = map2 (curry Free) us' fpTs;
   702                       val xysets = map (pair x) (ys ~~ sets);
   707                       val xysets = map (pair x) (ys ~~ sets);
   703                       val ppremss = map (mk_raw_prem_prems names_lthy') ys;
   708                       val ppremss = map (mk_raw_prem_prems names_lthy') ys;
   704                     in
   709                     in
   705                       flat (map2 (map o apfst o cons) xysets ppremss)
   710                       flat (map2 (map o apfst o cons) xysets ppremss)
   706                     end)
   711                     end)
   707                 | i => [([], (i + 1, x))])
   712                 | kk => [([], (kk + 1, x))])
   708               | mk_raw_prem_prems _ _ = [];
   713               | mk_raw_prem_prems _ _ = [];
   709 
   714 
   710             fun close_prem_prem xs t =
   715             fun close_prem_prem xs t =
   711               fold_rev Logic.all (map Free (drop (nn + length xs)
   716               fold_rev Logic.all (map Free (drop (nn + length xs)
   712                 (rev (Term.add_frees t (map dest_Free xs @ phis'))))) t;
   717                 (rev (Term.add_frees t (map dest_Free xs @ ps'))))) t;
   713 
   718 
   714             fun mk_prem_prem xs (xysets, (j, x)) =
   719             fun mk_prem_prem xs (xysets, (j, x)) =
   715               close_prem_prem xs (Logic.list_implies (map (fn (x', (y, set)) =>
   720               close_prem_prem xs (Logic.list_implies (map (fn (x', (y, set)) =>
   716                   HOLogic.mk_Trueprop (HOLogic.mk_mem (y, set $ x'))) xysets,
   721                   HOLogic.mk_Trueprop (HOLogic.mk_mem (y, set $ x'))) xysets,
   717                 HOLogic.mk_Trueprop (nth phis (j - 1) $ x)));
   722                 HOLogic.mk_Trueprop (nth ps (j - 1) $ x)));
   718 
   723 
   719             fun mk_raw_prem phi ctr ctr_Ts =
   724             fun mk_raw_prem phi ctr ctr_Ts =
   720               let
   725               let
   721                 val (xs, names_lthy') = names_lthy |> mk_Frees "x" ctr_Ts;
   726                 val (xs, names_lthy') = names_lthy |> mk_Frees "x" ctr_Ts;
   722                 val pprems = maps (mk_raw_prem_prems names_lthy') xs;
   727                 val pprems = maps (mk_raw_prem_prems names_lthy') xs;
   723               in (xs, pprems, HOLogic.mk_Trueprop (phi $ Term.list_comb (ctr, xs))) end;
   728               in (xs, pprems, HOLogic.mk_Trueprop (phi $ Term.list_comb (ctr, xs))) end;
   724 
   729 
   725             fun mk_prem (xs, raw_pprems, concl) =
   730             fun mk_prem (xs, raw_pprems, concl) =
   726               fold_rev Logic.all xs (Logic.list_implies (map (mk_prem_prem xs) raw_pprems, concl));
   731               fold_rev Logic.all xs (Logic.list_implies (map (mk_prem_prem xs) raw_pprems, concl));
   727 
   732 
   728             val raw_premss = map3 (map2 o mk_raw_prem) phis ctrss ctr_Tsss;
   733             val raw_premss = map3 (map2 o mk_raw_prem) ps ctrss ctr_Tsss;
   729 
   734 
   730             val goal =
   735             val goal =
   731               Library.foldr (Logic.list_implies o apfst (map mk_prem)) (raw_premss,
   736               Library.foldr (Logic.list_implies o apfst (map mk_prem)) (raw_premss,
   732                 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 (curry (op $)) phis us)));
   737                 HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj (map2 (curry (op $)) ps us)));
   733 
   738 
   734             val kksss = map (map (map (fst o snd) o #2)) raw_premss;
   739             val kksss = map (map (map (fst o snd) o #2)) raw_premss;
   735 
   740 
   736             val ctor_induct' = fp_induct OF (map mk_sumEN_tupled_balanced mss);
   741             val ctor_induct' = fp_induct OF (map mk_sumEN_tupled_balanced mss);
   737 
   742 
   738             val induct_thm =
   743             val thm =
   739               Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   744               Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   740                 mk_induct_tac ctxt nn ns mss kksss (flat ctr_defss) ctor_induct'
   745                 mk_induct_tac ctxt nn ns mss kksss (flat ctr_defss) ctor_induct'
   741                   nested_set_natural's pre_set_defss)
   746                   nested_set_natural's pre_set_defss)
   742               |> singleton (Proof_Context.export names_lthy lthy)
   747               |> singleton (Proof_Context.export names_lthy lthy)
       
   748               |> Thm.close_derivation;
   743           in
   749           in
   744             `(conj_dests nn) induct_thm
   750             `(conj_dests nn) thm
   745           end;
   751           end;
   746 
   752 
   747         (* TODO: Generate nicer names in case of clashes *)
   753         (* TODO: Generate nicer names in case of clashes *)
   748         val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss);
   754         val induct_cases = Datatype_Prop.indexify_names (maps (map base_name_of_ctr) ctrss);
   749 
   755 
   755 
   761 
   756             fun mk_goal fss frec_like xctr f xs fxs =
   762             fun mk_goal fss frec_like xctr f xs fxs =
   757               fold_rev (fold_rev Logic.all) (xs :: fss)
   763               fold_rev (fold_rev Logic.all) (xs :: fss)
   758                 (mk_Trueprop_eq (frec_like $ xctr, Term.list_comb (f, fxs)));
   764                 (mk_Trueprop_eq (frec_like $ xctr, Term.list_comb (f, fxs)));
   759 
   765 
   760             fun build_call frec_likes maybe_tick (T, U) =
   766             fun build_rec_like frec_likes maybe_tick (T, U) =
   761               if T = U then
   767               if T = U then
   762                 id_const T
   768                 id_const T
   763               else
   769               else
   764                 (case find_index (curry (op =) T) fpTs of
   770                 (case find_index (curry (op =) T) fpTs of
   765                   ~1 => build_map (build_call frec_likes maybe_tick) T U
   771                   ~1 => build_map (build_rec_like frec_likes maybe_tick) T U
   766                 | j => maybe_tick (nth us j) (nth frec_likes j));
   772                 | kk => maybe_tick (nth us kk) (nth frec_likes kk));
   767 
   773 
   768             fun mk_U maybe_mk_prodT =
   774             fun mk_U maybe_mk_prodT =
   769               typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs);
   775               typ_subst (map2 (fn fpT => fn C => (fpT, maybe_mk_prodT fpT C)) fpTs Cs);
   770 
   776 
   771             fun intr_calls frec_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) =
   777             fun intr_rec_likes frec_likes maybe_cons maybe_tick maybe_mk_prodT (x as Free (_, T)) =
   772               if member (op =) fpTs T then
   778               if member (op =) fpTs T then
   773                 maybe_cons x [build_call frec_likes (K I) (T, mk_U (K I) T) $ x]
   779                 maybe_cons x [build_rec_like frec_likes (K I) (T, mk_U (K I) T) $ x]
   774               else if exists_fp_subtype T then
   780               else if exists_fp_subtype T then
   775                 [build_call frec_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x]
   781                 [build_rec_like frec_likes maybe_tick (T, mk_U maybe_mk_prodT T) $ x]
   776               else
   782               else
   777                 [x];
   783                 [x];
   778 
   784 
   779             val gxsss = map (map (maps (intr_calls gfolds (K I) (K I) (K I)))) xsss;
   785             val gxsss = map (map (maps (intr_rec_likes gfolds (K I) (K I) (K I)))) xsss;
   780             val hxsss = map (map (maps (intr_calls hrecs cons tick (curry HOLogic.mk_prodT)))) xsss;
   786             val hxsss =
       
   787               map (map (maps (intr_rec_likes hrecs cons tick (curry HOLogic.mk_prodT)))) xsss;
   781 
   788 
   782             val fold_goalss = map5 (map4 o mk_goal gss) gfolds xctrss gss xsss gxsss;
   789             val fold_goalss = map5 (map4 o mk_goal gss) gfolds xctrss gss xsss gxsss;
   783             val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss;
   790             val rec_goalss = map5 (map4 o mk_goal hss) hrecs xctrss hss xsss hxsss;
   784 
   791 
   785             val fold_tacss =
   792             val fold_tacss =
   787                 ctr_defss;
   794                 ctr_defss;
   788             val rec_tacss =
   795             val rec_tacss =
   789               map2 (map o mk_rec_like_tac pre_map_defs nesting_map_ids rec_defs) fp_rec_thms
   796               map2 (map o mk_rec_like_tac pre_map_defs nesting_map_ids rec_defs) fp_rec_thms
   790                 ctr_defss;
   797                 ctr_defss;
   791 
   798 
   792             fun prove goal tac = Skip_Proof.prove lthy [] [] goal (tac o #context);
   799             fun prove goal tac =
       
   800               Skip_Proof.prove lthy [] [] goal (tac o #context)
       
   801               |> Thm.close_derivation;
   793           in
   802           in
   794             (map2 (map2 prove) fold_goalss fold_tacss,
   803             (map2 (map2 prove) fold_goalss fold_tacss,
   795              map2 (map2 prove) rec_goalss rec_tacss)
   804              map2 (map2 prove) rec_goalss rec_tacss)
   796           end;
   805           end;
   797 
   806 
   820       end;
   829       end;
   821 
   830 
   822     fun derive_coinduct_unfold_corec_thms_for_types (((ctrss, _, ctr_defss, wrap_ress), (unfolds,
   831     fun derive_coinduct_unfold_corec_thms_for_types (((ctrss, _, ctr_defss, wrap_ress), (unfolds,
   823         corecs, unfold_defs, corec_defs)), lthy) =
   832         corecs, unfold_defs, corec_defs)), lthy) =
   824       let
   833       let
       
   834         val nesting_rel_eqs = map rel_eq_of_bnf nesting_bnfs;
       
   835 
   825         val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress;
   836         val discss = map (map (mk_disc_or_sel As) o #1) wrap_ress;
   826         val selsss = map #2 wrap_ress;
   837         val selsss = map (map (map (mk_disc_or_sel As)) o #2) wrap_ress;
   827         val disc_thmsss = map #6 wrap_ress;
   838         val exhaust_thms = map #3 wrap_ress;
   828         val discIss = map #7 wrap_ress;
   839         val disc_thmsss = map #7 wrap_ress;
   829         val sel_thmsss = map #8 wrap_ress;
   840         val discIss = map #8 wrap_ress;
   830 
   841         val sel_thmsss = map #9 wrap_ress;
   831         val (us', _) =
   842 
       
   843         val (((rs, us'), vs'), names_lthy) =
   832           lthy
   844           lthy
   833           |> Variable.variant_fixes fp_b_names;
   845           |> mk_Frees "R" (map (fn T => mk_pred2T T T) fpTs)
       
   846           ||>> Variable.variant_fixes fp_b_names
       
   847           ||>> Variable.variant_fixes (map (suffix "'") fp_b_names);
   834 
   848 
   835         val us = map2 (curry Free) us' fpTs;
   849         val us = map2 (curry Free) us' fpTs;
   836 
   850         val udiscss = map2 (map o rapp) us discss;
   837         val (coinduct_thms, coinduct_thm) =
   851         val uselsss = map2 (map o map o rapp) us selsss;
       
   852 
       
   853         val vs = map2 (curry Free) vs' fpTs;
       
   854         val vdiscss = map2 (map o rapp) vs discss;
       
   855         val vselsss = map2 (map o map o rapp) vs selsss;
       
   856 
       
   857         val ((coinduct_thms, coinduct_thm), (strong_coinduct_thms, strong_coinduct_thm)) =
   838           let
   858           let
       
   859             val uvrs = map3 (fn r => fn u => fn v => r $ u $ v) rs us vs;
       
   860             val uv_eqs = map2 (curry HOLogic.mk_eq) us vs;
       
   861             val strong_rs =
       
   862               map4 (fn u => fn v => fn uvr => fn uv_eq =>
       
   863                 fold_rev Term.lambda [u, v] (HOLogic.mk_disj (uvr, uv_eq))) us vs uvrs uv_eqs;
       
   864 
       
   865             fun build_rel_step build_arg (Type (s, Ts)) =
       
   866               let
       
   867                 val bnf = the (bnf_of lthy s);
       
   868                 val live = live_of_bnf bnf;
       
   869                 val rel = mk_rel live Ts Ts (rel_of_bnf bnf);
       
   870                 val Ts' = map domain_type (fst (strip_typeN live (fastype_of rel)));
       
   871               in Term.list_comb (rel, map build_arg Ts') end;
       
   872 
       
   873             fun build_rel rs' T =
       
   874               (case find_index (curry (op =) T) fpTs of
       
   875                 ~1 =>
       
   876                 if exists_fp_subtype T then build_rel_step (build_rel rs') T
       
   877                 else HOLogic.eq_const T
       
   878               | kk => nth rs' kk);
       
   879 
       
   880             fun build_rel_app rs' usel vsel =
       
   881               fold rapp [usel, vsel] (build_rel rs' (fastype_of usel));
       
   882 
       
   883             fun mk_prem_ctr_concls rs' n k udisc usels vdisc vsels =
       
   884               (if k = n then [] else [HOLogic.mk_eq (udisc, vdisc)]) @
       
   885               (if null usels then
       
   886                  []
       
   887                else
       
   888                  [Library.foldr HOLogic.mk_imp (if n = 1 then [] else [udisc, vdisc],
       
   889                     Library.foldr1 HOLogic.mk_conj (map2 (build_rel_app rs') usels vsels))]);
       
   890 
       
   891             fun mk_prem_concl rs' n udiscs uselss vdiscs vselss =
       
   892               Library.foldr1 HOLogic.mk_conj
       
   893                 (flat (map5 (mk_prem_ctr_concls rs' n) (1 upto n) udiscs uselss vdiscs vselss))
       
   894               handle List.Empty => @{term True};
       
   895 
       
   896             fun mk_prem rs' uvr u v n udiscs uselss vdiscs vselss =
       
   897               fold_rev Logic.all [u, v] (Logic.mk_implies (HOLogic.mk_Trueprop uvr,
       
   898                 HOLogic.mk_Trueprop (mk_prem_concl rs' n udiscs uselss vdiscs vselss)));
       
   899 
       
   900             val concl =
       
   901               HOLogic.mk_Trueprop (Library.foldr1 HOLogic.mk_conj
       
   902                 (map3 (fn uvr => fn u => fn v => HOLogic.mk_imp (uvr, HOLogic.mk_eq (u, v)))
       
   903                    uvrs us vs));
       
   904 
       
   905             fun mk_goal rs' =
       
   906               Logic.list_implies (map8 (mk_prem rs') uvrs us vs ns udiscss uselsss vdiscss vselsss,
       
   907                 concl);
       
   908 
       
   909             val goal = mk_goal rs;
       
   910             val strong_goal = mk_goal strong_rs;
       
   911 
       
   912             fun prove dtor_coinduct' goal =
       
   913               Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
       
   914                 mk_coinduct_tac ctxt nesting_rel_eqs nn ns dtor_coinduct' pre_rel_defs dtor_ctors
       
   915                   exhaust_thms ctr_defss disc_thmsss sel_thmsss)
       
   916               |> singleton (Proof_Context.export names_lthy lthy)
       
   917               |> Thm.close_derivation;
       
   918 
   839             fun postproc nn thm =
   919             fun postproc nn thm =
   840               Thm.permute_prems 0 nn
   920               Thm.permute_prems 0 nn
   841                 (if nn = 1 then thm RS mp else funpow nn (fn thm => thm RS @{thm mp_conj}) thm)
   921                 (if nn = 1 then thm RS mp
   842               |> Drule.zero_var_indexes;
   922                  else funpow nn (fn thm => reassoc_conjs (thm RS mp_conj)) thm)
   843 
   923               |> Drule.zero_var_indexes
   844             val coinduct_thm = fp_induct;
   924               |> `(conj_dests nn);
   845           in
   925           in
   846             `(conj_dests nn) coinduct_thm
   926             (postproc nn (prove fp_induct goal), postproc nn (prove fp_strong_induct strong_goal))
   847           end;
   927           end;
   848 
   928 
   849         fun mk_maybe_not pos = not pos ? HOLogic.mk_not;
   929         fun mk_maybe_not pos = not pos ? HOLogic.mk_not;
   850 
   930 
   851         val z = the_single zs;
   931         val z = the_single zs;
   857             fun mk_goal pfss c cps fcorec_like n k ctr m cfs' =
   937             fun mk_goal pfss c cps fcorec_like n k ctr m cfs' =
   858               fold_rev (fold_rev Logic.all) ([c] :: pfss)
   938               fold_rev (fold_rev Logic.all) ([c] :: pfss)
   859                 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps,
   939                 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps,
   860                    mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs'))));
   940                    mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs'))));
   861 
   941 
   862             fun build_call frec_likes maybe_tack (T, U) =
   942             fun build_corec_like fcorec_likes maybe_tack (T, U) =
   863               if T = U then
   943               if T = U then
   864                 id_const T
   944                 id_const T
   865               else
   945               else
   866                 (case find_index (curry (op =) U) fpTs of
   946                 (case find_index (curry (op =) U) fpTs of
   867                   ~1 => build_map (build_call frec_likes maybe_tack) T U
   947                   ~1 => build_map (build_corec_like fcorec_likes maybe_tack) T U
   868                 | j => maybe_tack (nth cs j, nth us j) (nth frec_likes j));
   948                 | kk => maybe_tack (nth cs kk, nth us kk) (nth fcorec_likes kk));
   869 
   949 
   870             fun mk_U maybe_mk_sumT =
   950             fun mk_U maybe_mk_sumT =
   871               typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs);
   951               typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs);
   872 
   952 
   873             fun intr_calls frec_likes maybe_mk_sumT maybe_tack cqf =
   953             fun intr_corec_likes fcorec_likes maybe_mk_sumT maybe_tack cqf =
   874               let val T = fastype_of cqf in
   954               let val T = fastype_of cqf in
   875                 if exists_subtype (member (op =) Cs) T then
   955                 if exists_subtype (member (op =) Cs) T then
   876                   build_call frec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf
   956                   build_corec_like fcorec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf
   877                 else
   957                 else
   878                   cqf
   958                   cqf
   879               end;
   959               end;
   880 
   960 
   881             val crgsss' = map (map (map (intr_calls gunfolds (K I) (K I)))) crgsss;
   961             val crgsss' = map (map (map (intr_corec_likes gunfolds (K I) (K I)))) crgsss;
   882             val cshsss' = map (map (map (intr_calls hcorecs (curry mk_sumT) (tack z)))) cshsss;
   962             val cshsss' =
       
   963               map (map (map (intr_corec_likes hcorecs (curry mk_sumT) (tack z)))) cshsss;
   883 
   964 
   884             val unfold_goalss =
   965             val unfold_goalss =
   885               map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss';
   966               map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss';
   886             val corec_goalss =
   967             val corec_goalss =
   887               map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss';
   968               map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss';
   934             val corec_tacss =
  1015             val corec_tacss =
   935               map3 (map oo mk_disc_corec_like_iff_tac) case_splitss' corec_thmss disc_thmsss;
  1016               map3 (map oo mk_disc_corec_like_iff_tac) case_splitss' corec_thmss disc_thmsss;
   936 
  1017 
   937             fun prove goal tac =
  1018             fun prove goal tac =
   938               Skip_Proof.prove lthy [] [] goal (tac o #context)
  1019               Skip_Proof.prove lthy [] [] goal (tac o #context)
   939               |> Thm.close_derivation
  1020               |> singleton (Proof_Context.export names_lthy0 no_defs_lthy)
   940               |> singleton (Proof_Context.export names_lthy no_defs_lthy);
  1021               |> Thm.close_derivation;
   941 
  1022 
   942             fun proves [_] [_] = []
  1023             fun proves [_] [_] = []
   943               | proves goals tacs = map2 prove goals tacs;
  1024               | proves goals tacs = map2 prove goals tacs;
   944           in
  1025           in
   945             (map2 proves unfold_goalss unfold_tacss,
  1026             (map2 proves unfold_goalss unfold_tacss,
   981         val anonymous_notes =
  1062         val anonymous_notes =
   982           [(flat safe_unfold_thmss @ flat safe_corec_thmss, simp_attrs)]
  1063           [(flat safe_unfold_thmss @ flat safe_corec_thmss, simp_attrs)]
   983           |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])]));
  1064           |> map (fn (thms, attrs) => ((Binding.empty, attrs), [(thms, [])]));
   984 
  1065 
   985         val common_notes =
  1066         val common_notes =
   986           (if nn > 1 then [(coinductN, [coinduct_thm], [])] (* FIXME: attribs *) else [])
  1067           (if nn > 1 then
       
  1068              (* FIXME: attribs *)
       
  1069              [(coinductN, [coinduct_thm], []),
       
  1070               (strong_coinductN, [strong_coinduct_thm], [])]
       
  1071            else
       
  1072              [])
   987           |> map (fn (thmN, thms, attrs) =>
  1073           |> map (fn (thmN, thms, attrs) =>
   988             ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])]));
  1074             ((Binding.qualify true fp_common_name (Binding.name thmN), attrs), [(thms, [])]));
   989 
  1075 
   990         val notes =
  1076         val notes =
   991           [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *)
  1077           [(coinductN, map single coinduct_thms, []), (* FIXME: attribs *)
   995            (disc_unfold_iffsN, disc_unfold_iff_thmss, simp_attrs),
  1081            (disc_unfold_iffsN, disc_unfold_iff_thmss, simp_attrs),
   996            (disc_unfoldsN, disc_unfold_thmss, simp_attrs),
  1082            (disc_unfoldsN, disc_unfold_thmss, simp_attrs),
   997            (sel_unfoldsN, sel_unfold_thmss, simp_attrs),
  1083            (sel_unfoldsN, sel_unfold_thmss, simp_attrs),
   998            (sel_corecsN, sel_corec_thmss, simp_attrs),
  1084            (sel_corecsN, sel_corec_thmss, simp_attrs),
   999            (simpsN, simp_thmss, []),
  1085            (simpsN, simp_thmss, []),
       
  1086            (strong_coinductN, map single strong_coinduct_thms, []), (* FIXME: attribs *)
  1000            (unfoldsN, unfold_thmss, [])]
  1087            (unfoldsN, unfold_thmss, [])]
  1001           |> maps (fn (thmN, thmss, attrs) =>
  1088           |> maps (fn (thmN, thmss, attrs) =>
  1002             map_filter (fn (_, []) => NONE | (b, thms) =>
  1089             map_filter (fn (_, []) => NONE | (b, thms) =>
  1003               SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs),
  1090               SOME ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), attrs),
  1004                 [(thms, [])])) (fp_bs ~~ thmss));
  1091                 [(thms, [])])) (fp_bs ~~ thmss));