src/HOL/BNF/Tools/bnf_fp_def_sugar.ML
changeset 49683 78a3d5006cf1
parent 49682 f57af1c46f99
child 49693 393d7242adaf
equal deleted inserted replaced
49682:f57af1c46f99 49683:78a3d5006cf1
   111 fun liveness_of_fp_bnf n bnf =
   111 fun liveness_of_fp_bnf n bnf =
   112   (case T_of_bnf bnf of
   112   (case T_of_bnf bnf of
   113     Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts
   113     Type (_, Ts) => map (not o member (op =) (deads_of_bnf bnf)) Ts
   114   | _ => replicate n false);
   114   | _ => replicate n false);
   115 
   115 
   116 fun tack z_name (c, u) f =
       
   117   let val z = Free (z_name, mk_sumT (fastype_of u, fastype_of c)) in
       
   118     Term.lambda z (mk_sum_case (Term.lambda u u, Term.lambda c (f $ c)) $ z)
       
   119   end;
       
   120 
       
   121 fun cannot_merge_types () = error "Mutually recursive types must have the same type parameters";
   116 fun cannot_merge_types () = error "Mutually recursive types must have the same type parameters";
   122 
   117 
   123 fun merge_type_arg T T' = if T = T' then T else cannot_merge_types ();
   118 fun merge_type_arg T T' = if T = T' then T else cannot_merge_types ();
   124 
   119 
   125 fun merge_type_args (As, As') =
   120 fun merge_type_args (As, As') =
   275     val nested_bnfs = nesty_bnfs Xs;
   270     val nested_bnfs = nesty_bnfs Xs;
   276 
   271 
   277     val pre_map_defs = map map_def_of_bnf pre_bnfs;
   272     val pre_map_defs = map map_def_of_bnf pre_bnfs;
   278     val pre_set_defss = map set_defs_of_bnf pre_bnfs;
   273     val pre_set_defss = map set_defs_of_bnf pre_bnfs;
   279     val pre_rel_defs = map rel_def_of_bnf pre_bnfs;
   274     val pre_rel_defs = map rel_def_of_bnf pre_bnfs;
       
   275     val nested_map_comps'' = map ((fn thm => thm RS sym) o map_comp_of_bnf) nested_bnfs;
   280     val nested_map_comp's = map map_comp'_of_bnf nested_bnfs;
   276     val nested_map_comp's = map map_comp'_of_bnf nested_bnfs;
   281     val nested_map_ids'' = map (unfold_thms lthy @{thms id_def} o map_id_of_bnf) nested_bnfs;
   277     val nested_map_ids'' = map (unfold_thms lthy @{thms id_def} o map_id_of_bnf) nested_bnfs;
   282     val nesting_map_ids'' = map (unfold_thms lthy @{thms id_def} o map_id_of_bnf) nesting_bnfs;
   278     val nesting_map_ids'' = map (unfold_thms lthy @{thms id_def} o map_id_of_bnf) nesting_bnfs;
   283     val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs;
   279     val nested_set_natural's = maps set_natural'_of_bnf nested_bnfs;
   284     val nesting_set_natural's = maps set_natural'_of_bnf nesting_bnfs;
   280     val nesting_set_natural's = maps set_natural'_of_bnf nesting_bnfs;
   310 
   306 
   311     val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold)));
   307     val fp_fold_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_fold)));
   312     val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec)));
   308     val fp_rec_fun_Ts = fst (split_last (binder_types (fastype_of any_fp_rec)));
   313 
   309 
   314     val (((fold_only as (gss, _, _), rec_only as (hss, _, _)),
   310     val (((fold_only as (gss, _, _), rec_only as (hss, _, _)),
   315           (zs, cs, cpss, unfold_only as ((pgss, crgsss), _), corec_only as ((phss, cshsss), _))),
   311           (cs, cpss, unfold_only as ((pgss, crssss, cgssss), (_, g_Tsss, _)),
   316          names_lthy0) =
   312            corec_only as ((phss, csssss, chssss), (_, h_Tsss, _)))), names_lthy0) =
   317       if lfp then
   313       if lfp then
   318         let
   314         let
   319           val y_Tsss =
   315           val y_Tsss =
   320             map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type)
   316             map3 (fn n => fn ms => map2 dest_tupleT ms o dest_sumTN_balanced n o domain_type)
   321               ns mss fp_fold_fun_Ts;
   317               ns mss fp_fold_fun_Ts;
   342 
   338 
   343           val hss = map2 (map2 retype_free) h_Tss gss;
   339           val hss = map2 (map2 retype_free) h_Tss gss;
   344           val zsss = map2 (map2 (map2 retype_free)) z_Tsss ysss;
   340           val zsss = map2 (map2 (map2 retype_free)) z_Tsss ysss;
   345         in
   341         in
   346           ((((gss, g_Tss, ysss), (hss, h_Tss, zsss)),
   342           ((((gss, g_Tss, ysss), (hss, h_Tss, zsss)),
   347             ([], [], [], (([], []), ([], [])), (([], []), ([], [])))), lthy)
   343             ([], [], (([], [], []), ([], [], [])), (([], [], []), ([], [], [])))), lthy)
   348         end
   344         end
   349       else
   345       else
   350         let
   346         let
   351           (*avoid "'a itself" arguments in coiterators and corecursors*)
   347           (*avoid "'a itself" arguments in coiterators and corecursors*)
   352           val mss' =  map (fn [0] => [1] | ms => ms) mss;
   348           val mss' =  map (fn [0] => [1] | ms => ms) mss;
   371               val pf_Tss = map3 flat_preds_predsss_gettersss p_Tss q_Tssss f_Tssss;
   367               val pf_Tss = map3 flat_preds_predsss_gettersss p_Tss q_Tssss f_Tssss;
   372             in (q_Tssss, f_sum_prod_Ts, f_Tsss, f_Tssss, pf_Tss) end;
   368             in (q_Tssss, f_sum_prod_Ts, f_Tsss, f_Tssss, pf_Tss) end;
   373 
   369 
   374           val (r_Tssss, g_sum_prod_Ts, g_Tsss, g_Tssss, pg_Tss) = mk_types single fp_fold_fun_Ts;
   370           val (r_Tssss, g_sum_prod_Ts, g_Tsss, g_Tssss, pg_Tss) = mk_types single fp_fold_fun_Ts;
   375 
   371 
   376           val ((((Free (z, _), cs), pss), gssss), lthy) =
   372           val (((cs, pss), gssss), lthy) =
   377             lthy
   373             lthy
   378             |> yield_singleton (mk_Frees "z") dummyT
   374             |> mk_Frees "a" Cs
   379             ||>> mk_Frees "a" Cs
       
   380             ||>> mk_Freess "p" p_Tss
   375             ||>> mk_Freess "p" p_Tss
   381             ||>> mk_Freessss "g" g_Tssss;
   376             ||>> mk_Freessss "g" g_Tssss;
   382           val rssss = map (map (map (fn [] => []))) r_Tssss;
   377           val rssss = map (map (map (fn [] => []))) r_Tssss;
   383 
   378 
   384           fun proj_corecT proj (Type (s as @{type_name sum}, Ts as [T, U])) =
   379           fun proj_corecT proj (Type (s as @{type_name sum}, Ts as [T, U])) =
   399             ||>> mk_Freessss "h" (map (map (map tl)) h_Tssss);
   394             ||>> mk_Freessss "h" (map (map (map tl)) h_Tssss);
   400           val hssss = map2 (map2 (map2 cons)) hssss_hd hssss_tl;
   395           val hssss = map2 (map2 (map2 cons)) hssss_hd hssss_tl;
   401 
   396 
   402           val cpss = map2 (map o rapp) cs pss;
   397           val cpss = map2 (map o rapp) cs pss;
   403 
   398 
   404           fun build_sum_inj mk_inj (T, U) =
   399           fun mk_terms qssss fssss =
   405             if T = U then
       
   406               id_const T
       
   407             else
       
   408               (case (T, U) of
       
   409                 (Type (s, _), Type (s', _)) =>
       
   410                 if s = s' then build_map (build_sum_inj mk_inj) T U
       
   411                 else uncurry mk_inj (dest_sumT U)
       
   412               | _ => uncurry mk_inj (dest_sumT U));
       
   413 
       
   414           fun build_dtor_corec_arg _ [] [cf] = cf
       
   415             | build_dtor_corec_arg T [cq] [cf, cf'] =
       
   416               mk_If cq (build_sum_inj Inl_const (fastype_of cf, T) $ cf)
       
   417                 (build_sum_inj Inr_const (fastype_of cf', T) $ cf')
       
   418 
       
   419           fun mk_terms f_Tsss qssss fssss =
       
   420             let
   400             let
   421               val pfss = map3 flat_preds_predsss_gettersss pss qssss fssss;
   401               val pfss = map3 flat_preds_predsss_gettersss pss qssss fssss;
   422               val cqssss = map2 (map o map o map o rapp) cs qssss;
   402               val cqssss = map2 (map o map o map o rapp) cs qssss;
   423               val cfssss = map2 (map o map o map o rapp) cs fssss;
   403               val cfssss = map2 (map o map o map o rapp) cs fssss;
   424               val cqfsss = map3 (map3 (map3 build_dtor_corec_arg)) f_Tsss cqssss cfssss;
   404             in (pfss, cqssss, cfssss) end;
   425             in (pfss, cqfsss) end;
       
   426         in
   405         in
   427           (((([], [], []), ([], [], [])),
   406           (((([], [], []), ([], [], [])),
   428             ([z], cs, cpss, (mk_terms g_Tsss rssss gssss, (g_sum_prod_Ts, pg_Tss)),
   407             (cs, cpss, (mk_terms rssss gssss, (g_sum_prod_Ts, g_Tsss, pg_Tss)),
   429              (mk_terms h_Tsss sssss hssss, (h_sum_prod_Ts, ph_Tss)))), lthy)
   408              (mk_terms sssss hssss, (h_sum_prod_Ts, h_Tsss, ph_Tss)))), lthy)
   430         end;
   409         end;
   431 
   410 
   432     fun define_ctrs_case_for_type (((((((((((((((((((((((((fp_bnf, fp_b), fpT), C), ctor), dtor),
   411     fun define_ctrs_case_for_type (((((((((((((((((((((((((fp_bnf, fp_b), fpT), C), ctor), dtor),
   433             fp_fold), fp_rec), ctor_dtor), dtor_ctor), ctor_inject), pre_map_def), pre_set_defs),
   412             fp_fold), fp_rec), ctor_dtor), dtor_ctor), ctor_inject), pre_map_def), pre_set_defs),
   434           pre_rel_def), fp_map_thm), fp_set_thms), fp_rel_thm), n), ks), ms), ctr_bindings),
   413           pre_rel_def), fp_map_thm), fp_set_thms), fp_rel_thm), n), ks), ms), ctr_bindings),
   666 
   645 
   667         fun define_unfold_corec no_defs_lthy =
   646         fun define_unfold_corec no_defs_lthy =
   668           let
   647           let
   669             val B_to_fpT = C --> fpT;
   648             val B_to_fpT = C --> fpT;
   670 
   649 
       
   650             fun build_sum_inj mk_inj (T, U) =
       
   651               if T = U then
       
   652                 id_const T
       
   653               else
       
   654                 (case (T, U) of
       
   655                   (Type (s, _), Type (s', _)) =>
       
   656                   if s = s' then build_map (build_sum_inj mk_inj) T U
       
   657                   else uncurry mk_inj (dest_sumT U)
       
   658                 | _ => uncurry mk_inj (dest_sumT U));
       
   659 
       
   660             fun build_dtor_corec_like_arg _ [] [cf] = cf
       
   661               | build_dtor_corec_like_arg T [cq] [cf, cf'] =
       
   662                 mk_If cq (build_sum_inj Inl_const (fastype_of cf, T) $ cf)
       
   663                   (build_sum_inj Inr_const (fastype_of cf', T) $ cf')
       
   664 
       
   665             val crgsss = map3 (map3 (map3 build_dtor_corec_like_arg)) g_Tsss crssss cgssss;
       
   666             val cshsss = map3 (map3 (map3 build_dtor_corec_like_arg)) h_Tsss csssss chssss;
       
   667 
   671             fun mk_preds_getterss_join c n cps sum_prod_T cqfss =
   668             fun mk_preds_getterss_join c n cps sum_prod_T cqfss =
   672               Term.lambda c (mk_IfN sum_prod_T cps
   669               Term.lambda c (mk_IfN sum_prod_T cps
   673                 (map2 (mk_InN_balanced sum_prod_T n) (map HOLogic.mk_tuple cqfss) (1 upto n)));
   670                 (map2 (mk_InN_balanced sum_prod_T n) (map HOLogic.mk_tuple cqfss) (1 upto n)));
   674 
   671 
   675             fun generate_corec_like (suf, fp_rec_like, ((pfss, cqfsss), (f_sum_prod_Ts,
   672             fun generate_corec_like (suf, fp_rec_like, (cqfsss, ((pfss, _, _), (f_sum_prod_Ts, _,
   676                 pf_Tss))) =
   673                 pf_Tss)))) =
   677               let
   674               let
   678                 val res_T = fold_rev (curry (op --->)) pf_Tss B_to_fpT;
   675                 val res_T = fold_rev (curry (op --->)) pf_Tss B_to_fpT;
   679                 val binding = qualify false fp_b_name (Binding.suffix_name ("_" ^ suf) fp_b);
   676                 val binding = qualify false fp_b_name (Binding.suffix_name ("_" ^ suf) fp_b);
   680                 val spec =
   677                 val spec =
   681                   mk_Trueprop_eq (lists_bmoc pfss (Free (Binding.name_of binding, res_T)),
   678                   mk_Trueprop_eq (lists_bmoc pfss (Free (Binding.name_of binding, res_T)),
   682                     Term.list_comb (fp_rec_like,
   679                     Term.list_comb (fp_rec_like,
   683                       map5 mk_preds_getterss_join cs ns cpss f_sum_prod_Ts cqfsss));
   680                       map5 mk_preds_getterss_join cs ns cpss f_sum_prod_Ts cqfsss));
   684               in (binding, spec) end;
   681               in (binding, spec) end;
   685 
   682 
   686             val corec_like_infos =
   683             val corec_like_infos =
   687               [(unfoldN, fp_fold, unfold_only),
   684               [(unfoldN, fp_fold, (crgsss, unfold_only)),
   688                (corecN, fp_rec, corec_only)];
   685                (corecN, fp_rec, (cshsss, corec_only))];
   689 
   686 
   690             val (bindings, specs) = map generate_corec_like corec_like_infos |> split_list;
   687             val (bindings, specs) = map generate_corec_like corec_like_infos |> split_list;
   691 
   688 
   692             val ((csts, defs), (lthy', lthy)) = no_defs_lthy
   689             val ((csts, defs), (lthy', lthy)) = no_defs_lthy
   693               |> apfst split_list o fold_map2 (fn b => fn spec =>
   690               |> apfst split_list o fold_map2 (fn b => fn spec =>
   917                 fold_rev Term.lambda [u, v] (HOLogic.mk_disj (uvr, uv_eq))) us vs uvrs uv_eqs;
   914                 fold_rev Term.lambda [u, v] (HOLogic.mk_disj (uvr, uv_eq))) us vs uvrs uv_eqs;
   918 
   915 
   919             fun build_rel rs' T =
   916             fun build_rel rs' T =
   920               (case find_index (curry (op =) T) fpTs of
   917               (case find_index (curry (op =) T) fpTs of
   921                 ~1 =>
   918                 ~1 =>
   922                 if exists_fp_subtype T then build_rel_step (build_rel rs') T
   919                 if exists_fp_subtype T then build_rel_step (build_rel rs') T else HOLogic.eq_const T
   923                 else HOLogic.eq_const T
       
   924               | kk => nth rs' kk);
   920               | kk => nth rs' kk);
   925 
   921 
   926             fun build_rel_app rs' usel vsel =
   922             fun build_rel_app rs' usel vsel =
   927               fold rapp [usel, vsel] (build_rel rs' (fastype_of usel));
   923               fold rapp [usel, vsel] (build_rel rs' (fastype_of usel));
   928 
   924 
   972             (postproc nn (prove fp_induct goal), postproc nn (prove fp_strong_induct strong_goal))
   968             (postproc nn (prove fp_induct goal), postproc nn (prove fp_strong_induct strong_goal))
   973           end;
   969           end;
   974 
   970 
   975         fun mk_maybe_not pos = not pos ? HOLogic.mk_not;
   971         fun mk_maybe_not pos = not pos ? HOLogic.mk_not;
   976 
   972 
   977         val z = the_single zs;
       
   978         val gunfolds = map (lists_bmoc pgss) unfolds;
   973         val gunfolds = map (lists_bmoc pgss) unfolds;
   979         val hcorecs = map (lists_bmoc phss) corecs;
   974         val hcorecs = map (lists_bmoc phss) corecs;
   980 
   975 
   981         val (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss) =
   976         val (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss) =
   982           let
   977           let
   983             fun mk_goal pfss c cps fcorec_like n k ctr m cfs' =
   978             fun mk_goal pfss c cps fcorec_like n k ctr m cfs' =
   984               fold_rev (fold_rev Logic.all) ([c] :: pfss)
   979               fold_rev (fold_rev Logic.all) ([c] :: pfss)
   985                 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps,
   980                 (Logic.list_implies (seq_conds (HOLogic.mk_Trueprop oo mk_maybe_not) n k cps,
   986                    mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs'))));
   981                    mk_Trueprop_eq (fcorec_like $ c, Term.list_comb (ctr, take m cfs'))));
   987 
   982 
   988             fun build_corec_like fcorec_likes maybe_tack (T, U) =
   983             fun build_corec_like fcorec_likes (T, U) =
   989               if T = U then
   984               if T = U then
   990                 id_const T
   985                 id_const T
   991               else
   986               else
   992                 (case find_index (curry (op =) U) fpTs of
   987                 (case find_index (curry (op =) U) fpTs of
   993                   ~1 => build_map (build_corec_like fcorec_likes maybe_tack) T U
   988                   ~1 => build_map (build_corec_like fcorec_likes) T U
   994                 | kk => maybe_tack (nth cs kk, nth us kk) (nth fcorec_likes kk));
   989                 | kk => nth fcorec_likes kk);
   995 
   990 
   996             fun mk_U maybe_mk_sumT =
   991             val mk_U = typ_subst (map2 pair Cs fpTs);
   997               typ_subst (map2 (fn C => fn fpT => (maybe_mk_sumT fpT C, fpT)) Cs fpTs);
   992 
   998 
   993             fun intr_corec_likes fcorec_likes [] [cf] =
   999             fun intr_corec_likes fcorec_likes maybe_mk_sumT maybe_tack cqf =
   994                 let val T = fastype_of cf in
  1000               let val T = fastype_of cqf in
   995                   if exists_Cs_subtype T then build_corec_like fcorec_likes (T, mk_U T) $ cf else cf
  1001                 if exists_Cs_subtype T then
   996                 end
  1002                   build_corec_like fcorec_likes maybe_tack (T, mk_U maybe_mk_sumT T) $ cqf
   997               | intr_corec_likes fcorec_likes [cq] [cf, cf'] =
  1003                 else
   998                 mk_If cq (intr_corec_likes fcorec_likes [] [cf])
  1004                   cqf
   999                   (intr_corec_likes fcorec_likes [] [cf']);
       
  1000 
       
  1001             val crgsss = map2 (map2 (map2 (intr_corec_likes gunfolds))) crssss cgssss;
       
  1002             val cshsss = map2 (map2 (map2 (intr_corec_likes hcorecs))) csssss chssss;
       
  1003 
       
  1004             val unfold_goalss =
       
  1005               map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss;
       
  1006             val corec_goalss =
       
  1007               map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss;
       
  1008 
       
  1009             fun mk_map_if_distrib bnf =
       
  1010               let
       
  1011                 val mapx = map_of_bnf bnf;
       
  1012                 val live = live_of_bnf bnf;
       
  1013                 val ((Ts, T), U) = strip_typeN (live + 1) (fastype_of mapx) |>> split_last;
       
  1014                 val fs = Variable.variant_frees lthy [mapx] (map (pair "f") Ts);
       
  1015                 val t = Term.list_comb (mapx, map (Var o apfst (rpair 0)) fs);
       
  1016               in
       
  1017                 Drule.instantiate' (map (SOME o certifyT lthy) [U, T]) [SOME (certify lthy t)]
       
  1018                   @{thm if_distrib}
  1005               end;
  1019               end;
  1006 
  1020 
  1007             val crgsss' = map (map (map (intr_corec_likes gunfolds (K I) (K I)))) crgsss;
  1021             val nested_map_if_distribs = map mk_map_if_distrib nested_bnfs;
  1008             val cshsss' =
       
  1009               map (map (map (intr_corec_likes hcorecs (curry mk_sumT) (tack z)))) cshsss;
       
  1010 
       
  1011             val unfold_goalss =
       
  1012               map8 (map4 oooo mk_goal pgss) cs cpss gunfolds ns kss ctrss mss crgsss';
       
  1013             val corec_goalss =
       
  1014               map8 (map4 oooo mk_goal phss) cs cpss hcorecs ns kss ctrss mss cshsss';
       
  1015 
  1022 
  1016             val unfold_tacss =
  1023             val unfold_tacss =
  1017               map3 (map oo mk_corec_like_tac unfold_defs nesting_map_ids'') fp_fold_thms
  1024               map3 (map oo mk_corec_like_tac unfold_defs [] [] nesting_map_ids'' [])
  1018                 pre_map_defs ctr_defss;
  1025                 fp_fold_thms pre_map_defs ctr_defss;
  1019             val corec_tacss =
  1026             val corec_tacss =
  1020               map3 (map oo mk_corec_like_tac corec_defs nesting_map_ids'') fp_rec_thms pre_map_defs
  1027               map3 (map oo mk_corec_like_tac corec_defs nested_map_comps'' nested_map_comp's
  1021                 ctr_defss;
  1028                   (nested_map_ids'' @ nesting_map_ids'') nested_map_if_distribs)
       
  1029                 fp_rec_thms pre_map_defs ctr_defss;
  1022 
  1030 
  1023             fun prove goal tac =
  1031             fun prove goal tac =
  1024               Skip_Proof.prove lthy [] [] goal (tac o #context) |> Thm.close_derivation;
  1032               Skip_Proof.prove lthy [] [] goal (tac o #context) |> Thm.close_derivation;
  1025 
  1033 
  1026             val unfold_thmss = map2 (map2 prove) unfold_goalss unfold_tacss;
  1034             val unfold_thmss = map2 (map2 prove) unfold_goalss unfold_tacss;
  1027             val corec_thmss =
  1035             val corec_thmss = map2 (map2 prove) corec_goalss corec_tacss;
  1028               map2 (map2 prove) corec_goalss corec_tacss
       
  1029               |> map (map (unfold_thms lthy @{thms sum_case_if}));
       
  1030 
       
  1031             val unfold_safesss = map2 (map2 (map2 (curry (op =)))) crgsss' crgsss;
       
  1032             val corec_safesss = map2 (map2 (map2 (curry (op =)))) cshsss' cshsss;
       
  1033 
  1036 
  1034             val filter_safesss =
  1037             val filter_safesss =
  1035               map2 (map_filter (fn (safes, thm) => if forall I safes then SOME thm else NONE) oo
  1038               map2 (map_filter (fn (safes, thm) => if forall I safes then SOME thm else NONE) oo
  1036                 curry (op ~~));
  1039                 curry (op ~~)) (map2 (map2 (map2 (member (op =)))) cgssss crgsss);
  1037 
  1040 
  1038             val safe_unfold_thmss = filter_safesss unfold_safesss unfold_thmss;
  1041             val safe_unfold_thmss = filter_safesss unfold_thmss;
  1039             val safe_corec_thmss = filter_safesss corec_safesss corec_thmss;
  1042             val safe_corec_thmss = filter_safesss corec_thmss;
  1040           in
  1043           in
  1041             (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss)
  1044             (unfold_thmss, corec_thmss, safe_unfold_thmss, safe_corec_thmss)
  1042           end;
  1045           end;
  1043 
  1046 
  1044         val (disc_unfold_iff_thmss, disc_corec_iff_thmss) =
  1047         val (disc_unfold_iff_thmss, disc_corec_iff_thmss) =