src/HOL/Tools/BNF/bnf_fp_def_sugar.ML
changeset 57094 589ec121ce1a
parent 57091 1fa9c19ba2c9
child 57152 de1ed2c1c3bf
equal deleted inserted replaced
57093:c46fe1cb1d94 57094:589ec121ce1a
   827      (disc_corec_iff_thmss, simp_attrs),
   827      (disc_corec_iff_thmss, simp_attrs),
   828      (sel_corec_thmsss, simp_attrs))
   828      (sel_corec_thmsss, simp_attrs))
   829   end;
   829   end;
   830 
   830 
   831 fun define_co_datatypes prepare_constraint prepare_typ prepare_term fp construct_fp
   831 fun define_co_datatypes prepare_constraint prepare_typ prepare_term fp construct_fp
   832     (wrap_opts as (no_discs_sels, _), specs) no_defs_lthy0 =
   832     ((discs_sels0, no_code), specs) no_defs_lthy0 =
   833   let
   833   let
   834     (* TODO: sanity checks on arguments *)
   834     (* TODO: sanity checks on arguments *)
   835 
   835 
   836     val _ = if fp = Greatest_FP andalso no_discs_sels then
   836     val discs_sels = discs_sels0 orelse fp = Greatest_FP;
   837         error "Cannot define codatatypes without discriminators and selectors"
       
   838       else
       
   839         ();
       
   840 
   837 
   841     val nn = length specs;
   838     val nn = length specs;
   842     val fp_bs = map type_binding_of_spec specs;
   839     val fp_bs = map type_binding_of_spec specs;
   843     val fp_b_names = map Binding.name_of fp_bs;
   840     val fp_b_names = map Binding.name_of fp_bs;
   844     val fp_common_name = mk_common_name fp_b_names;
   841     val fp_common_name = mk_common_name fp_b_names;
  1113             val sel_defaultss = map (map (apsnd (prepare_term lthy))) raw_sel_defaultss
  1110             val sel_defaultss = map (map (apsnd (prepare_term lthy))) raw_sel_defaultss
  1114 
  1111 
  1115             fun ctr_spec_of disc_b ctr0 sel_bs sel_defs = (((disc_b, ctr0), sel_bs), sel_defs);
  1112             fun ctr_spec_of disc_b ctr0 sel_bs sel_defs = (((disc_b, ctr0), sel_bs), sel_defs);
  1116             val ctr_specs = map4 ctr_spec_of disc_bindings ctrs0 sel_bindingss sel_defaultss;
  1113             val ctr_specs = map4 ctr_spec_of disc_bindings ctrs0 sel_bindingss sel_defaultss;
  1117           in
  1114           in
  1118             free_constructors tacss ((wrap_opts, standard_binding), ctr_specs) lthy
  1115             free_constructors tacss (((discs_sels, no_code), standard_binding), ctr_specs) lthy
  1119           end;
  1116           end;
  1120 
  1117 
  1121         fun derive_maps_sets_rels
  1118         fun derive_maps_sets_rels
  1122           (ctr_sugar as {case_cong, discs, selss, ctrs, exhaust, disc_thmss, sel_thmss, ...} : ctr_sugar, lthy) =
  1119           (ctr_sugar as {case_cong, discs, selss, ctrs, exhaust, disc_thmss, sel_thmss, ...} : ctr_sugar, lthy) =
  1123           if live = 0 then
  1120           if live = 0 then
  1191                   val ((fs, ta), names_lthy) = names_lthy
  1188                   val ((fs, ta), names_lthy) = names_lthy
  1192                     |> mk_Frees "f" fTs
  1189                     |> mk_Frees "f" fTs
  1193                     ||>> yield_singleton (mk_Frees "a") TA;
  1190                     ||>> yield_singleton (mk_Frees "a") TA;
  1194                   val map_term = mk_map_of_bnf Ds As Bs fp_bnf;
  1191                   val map_term = mk_map_of_bnf Ds As Bs fp_bnf;
  1195                   val discsA = map (mk_disc_or_sel ADs) discs;
  1192                   val discsA = map (mk_disc_or_sel ADs) discs;
       
  1193 
  1196                   fun is_t_eq_t T t term =
  1194                   fun is_t_eq_t T t term =
  1197                     let
  1195                     let
  1198                       val (head, tail) = Term.strip_comb term;
  1196                       val (head, tail) = Term.strip_comb term;
  1199                     in
  1197                     in
  1200                       head aconv HOLogic.eq_const T andalso forall (fn u => u = t) tail
  1198                       head aconv HOLogic.eq_const T andalso forall (fn u => u = t) tail
  1201                     end;
  1199                     end;
       
  1200 
  1202                   val disc_map_iff_thms =
  1201                   val disc_map_iff_thms =
  1203                     let
  1202                     let
  1204                       val discsB = map (mk_disc_or_sel BDs) discs;
  1203                       val discsB = map (mk_disc_or_sel BDs) discs;
  1205                       val discsA_t = map (fn disc1 => Term.betapply (disc1, ta)) discsA;
  1204                       val discsA_t = map (fn disc1 => Term.betapply (disc1, ta)) discsA;
       
  1205 
  1206                       fun mk_goal (discA_t, discB) =
  1206                       fun mk_goal (discA_t, discB) =
  1207                           if head_of discA_t aconv @{const Not} orelse is_t_eq_t TA ta discA_t then
  1207                         if head_of discA_t aconv @{const Not} orelse is_t_eq_t TA ta discA_t then
  1208                             NONE
  1208                           NONE
  1209                           else
  1209                         else
  1210                             SOME (mk_Trueprop_eq
  1210                           SOME (mk_Trueprop_eq
  1211                               (betapply (discB, (Term.list_comb (map_term, fs) $ ta)), discA_t));
  1211                             (betapply (discB, (Term.list_comb (map_term, fs) $ ta)), discA_t));
       
  1212 
  1212                       val goals = map_filter mk_goal (discsA_t ~~ discsB);
  1213                       val goals = map_filter mk_goal (discsA_t ~~ discsB);
  1213                     in
  1214                     in
  1214                       if null goals then []
  1215                       if null goals then []
  1215                       else
  1216                       else
  1216                         Goal.prove_sorry lthy [] [] (Logic.mk_conjunction_balanced goals)
  1217                         Goal.prove_sorry lthy [] [] (Logic.mk_conjunction_balanced goals)
  1218                             mk_disc_map_iff_tac ctxt (certify ctxt ta) exhaust (flat disc_thmss)
  1219                             mk_disc_map_iff_tac ctxt (certify ctxt ta) exhaust (flat disc_thmss)
  1219                               map_thms)
  1220                               map_thms)
  1220                           |> Conjunction.elim_balanced (length goals)
  1221                           |> Conjunction.elim_balanced (length goals)
  1221                           |> Proof_Context.export names_lthy lthy
  1222                           |> Proof_Context.export names_lthy lthy
  1222                     end;
  1223                     end;
       
  1224 
  1223                   val sel_map_thms =
  1225                   val sel_map_thms =
  1224                     let
  1226                     let
  1225                       fun mk_sel_map_goal (discA, selA) =
  1227                       fun mk_sel_map_goal (discA, selA) =
  1226                         let
  1228                         let
  1227                           val premise = Term.betapply (discA, ta);
  1229                           val premise = Term.betapply (discA, ta);
  1234                           val rhs = (case map_rhs of
  1236                           val rhs = (case map_rhs of
  1235                             Const (@{const_name id}, _) => selA $ ta
  1237                             Const (@{const_name id}, _) => selA $ ta
  1236                             | _ => map_rhs $ (selA $ ta));
  1238                             | _ => map_rhs $ (selA $ ta));
  1237                           val conclusion = mk_Trueprop_eq (lhs, rhs);
  1239                           val conclusion = mk_Trueprop_eq (lhs, rhs);
  1238                         in
  1240                         in
  1239                           if is_t_eq_t TA ta premise then
  1241                           if is_t_eq_t TA ta premise then conclusion
  1240                             conclusion
  1242                           else Logic.mk_implies (HOLogic.mk_Trueprop premise, conclusion)
  1241                           else
       
  1242                             Logic.mk_implies (HOLogic.mk_Trueprop premise, conclusion)
       
  1243                         end;
  1243                         end;
       
  1244 
  1244                       val disc_sel_pairs = flat (map2 (fn disc => fn sels => map (pair disc) sels)
  1245                       val disc_sel_pairs = flat (map2 (fn disc => fn sels => map (pair disc) sels)
  1245                         discsA (map (map (mk_disc_or_sel ADs)) selss));
  1246                         discsA (map (map (mk_disc_or_sel ADs)) selss));
  1246                       val goals = map mk_sel_map_goal disc_sel_pairs;
  1247                       val goals = map mk_sel_map_goal disc_sel_pairs;
  1247                     in
  1248                     in
  1248                       if null goals then []
  1249                       if null goals then []
  1256                     end;
  1257                     end;
  1257                 in
  1258                 in
  1258                   (disc_map_iff_thms, sel_map_thms)
  1259                   (disc_map_iff_thms, sel_map_thms)
  1259                 end;
  1260                 end;
  1260 
  1261 
  1261               val ctr_argT_namess = map ((fn Ts => fold Term.add_tfree_namesT Ts []) o
  1262               val set_empty_thms =
  1262                 binder_types o fastype_of) ctrs;
  1263                 let
  1263               val setTs = map (HOLogic.dest_setT o range_type o fastype_of) sets;
  1264                   val ctr_argT_namess = map ((fn Ts => fold Term.add_tfree_namesT Ts []) o
  1264               val setT_names = map (fn T => the_single (Term.add_tfree_namesT T [])) setTs;
  1265                     binder_types o fastype_of) ctrs;
  1265               fun mk_set_empty_goal disc set T = Logic.mk_implies (HOLogic.mk_Trueprop (disc $ u),
  1266                   val setTs = map (HOLogic.dest_setT o range_type o fastype_of) sets;
  1266                 mk_Trueprop_eq (set $ u, HOLogic.mk_set T []));
  1267                   val setT_names = map (fn T => the_single (Term.add_tfree_namesT T [])) setTs;
  1267               val goals = map_filter I (flat
  1268 
  1268                 (map2 (fn names => fn disc =>
  1269                   fun mk_set_empty_goal disc set T =
  1269                   map3 (fn name => fn setT => fn set =>
  1270                     Logic.mk_implies (HOLogic.mk_Trueprop (disc $ u),
  1270                     if member (op =) names name then NONE
  1271                       mk_Trueprop_eq (set $ u, HOLogic.mk_set T []));
  1271                     else SOME (mk_set_empty_goal disc set setT))
  1272 
  1272                   setT_names setTs sets)
  1273                   val goals =
  1273                 ctr_argT_namess discs));
  1274                     if null discs then
  1274 
  1275                       []
  1275               val set_empty_thms = if null goals then []
  1276                     else
  1276                 else Goal.prove_sorry lthy [] [] (Logic.mk_conjunction_balanced goals)
  1277                       map_filter I (flat
  1277                   (fn {context = ctxt, prems = _} =>
  1278                         (map2 (fn names => fn disc =>
  1278                     mk_set_empty_tac ctxt (certify ctxt u) exhaust set_thms (flat disc_thmss))
  1279                           map3 (fn name => fn setT => fn set =>
  1279                   |> Conjunction.elim_balanced (length goals)
  1280                             if member (op =) names name then NONE
  1280                   |> Proof_Context.export names_lthy lthy;
  1281                             else SOME (mk_set_empty_goal disc set setT))
       
  1282                           setT_names setTs sets)
       
  1283                         ctr_argT_namess discs));
       
  1284                 in
       
  1285                   if null goals then
       
  1286                     []
       
  1287                   else
       
  1288                     Goal.prove_sorry lthy [] [] (Logic.mk_conjunction_balanced goals)
       
  1289                       (fn {context = ctxt, prems = _} =>
       
  1290                         mk_set_empty_tac ctxt (certify ctxt u) exhaust set_thms (flat disc_thmss))
       
  1291                       |> Conjunction.elim_balanced (length goals)
       
  1292                       |> Proof_Context.export names_lthy lthy
       
  1293                 end;
  1281 
  1294 
  1282               val rel_infos = (ctr_defs' ~~ cxIns, ctr_defs' ~~ cyIns);
  1295               val rel_infos = (ctr_defs' ~~ cxIns, ctr_defs' ~~ cyIns);
  1283 
  1296 
  1284               fun mk_rel_thm postproc ctr_defs' cxIn cyIn =
  1297               fun mk_rel_thm postproc ctr_defs' cxIn cyIn =
  1285                 fold_thms lthy ctr_defs'
  1298                 fold_thms lthy ctr_defs'