src/HOL/Codatatype/Tools/bnf_sugar.ML
changeset 49032 c2a7bedd57d8
parent 49031 632ee0da3c5b
child 49033 23ef2d429931
equal deleted inserted replaced
49031:632ee0da3c5b 49032:c2a7bedd57d8
    35 fun index_of_half_row _ 0 = 0
    35 fun index_of_half_row _ 0 = 0
    36   | index_of_half_row n j = index_of_half_row n (j - 1) + n - j;
    36   | index_of_half_row n j = index_of_half_row n (j - 1) + n - j;
    37 
    37 
    38 fun index_of_half_cell n j k = index_of_half_row n j + k - (j + 1);
    38 fun index_of_half_cell n j k = index_of_half_row n j + k - (j + 1);
    39 
    39 
       
    40 val mk_Trueprop_eq = HOLogic.mk_Trueprop o HOLogic.mk_eq;
       
    41 
       
    42 fun eta_expand_caseof_arg f xs = fold_rev Term.lambda xs (Term.list_comb (f, xs));
       
    43 
    40 fun prepare_sugar prep_term (((raw_ctrs, raw_caseof), disc_names), sel_namess) no_defs_lthy =
    44 fun prepare_sugar prep_term (((raw_ctrs, raw_caseof), disc_names), sel_namess) no_defs_lthy =
    41   let
    45   let
    42     (* TODO: sanity checks on arguments *)
    46     (* TODO: sanity checks on arguments *)
    43 
    47 
    44     (* TODO: normalize types of constructors w.r.t. each other *)
    48     (* TODO: normalize types of constructors w.r.t. each other *)
    76     val ms = map length ctr_Tss;
    80     val ms = map length ctr_Tss;
    77 
    81 
    78     val caseofB = mk_caseof As B;
    82     val caseofB = mk_caseof As B;
    79     val caseofB_Ts = map (fn Ts => Ts ---> B) ctr_Tss;
    83     val caseofB_Ts = map (fn Ts => Ts ---> B) ctr_Tss;
    80 
    84 
    81     val (((((xss, yss), fs), (v, v')), p), names_lthy) = no_defs_lthy |>
    85     val (((((((xss, yss), fs), gs), (v, v')), w), p), names_lthy) = no_defs_lthy |>
    82       mk_Freess "x" ctr_Tss
    86       mk_Freess "x" ctr_Tss
    83       ||>> mk_Freess "y" ctr_Tss
    87       ||>> mk_Freess "y" ctr_Tss
    84       ||>> mk_Frees "f" caseofB_Ts
    88       ||>> mk_Frees "f" caseofB_Ts
       
    89       ||>> mk_Frees "g" caseofB_Ts
    85       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "v") T
    90       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "v") T
       
    91       ||>> yield_singleton (mk_Frees "w") T
    86       ||>> yield_singleton (mk_Frees "P") HOLogic.boolT;
    92       ||>> yield_singleton (mk_Frees "P") HOLogic.boolT;
    87 
    93 
    88     val xctrs = map2 (curry Term.list_comb) ctrs xss;
    94     val xctrs = map2 (curry Term.list_comb) ctrs xss;
    89     val yctrs = map2 (curry Term.list_comb) ctrs yss;
    95     val yctrs = map2 (curry Term.list_comb) ctrs yss;
    90     val eta_fs = map2 (fn f => fn xs => fold_rev Term.lambda xs (Term.list_comb (f, xs))) fs xss;
    96 
       
    97     val eta_fs = map2 eta_expand_caseof_arg fs xss;
       
    98     val eta_gs = map2 eta_expand_caseof_arg gs xss;
    91 
    99 
    92     val exist_xs_v_eq_ctrs =
   100     val exist_xs_v_eq_ctrs =
    93       map2 (fn xctr => fn xs => list_exists_free xs (HOLogic.mk_eq (v, xctr))) xctrs xss;
   101       map2 (fn xctr => fn xs => list_exists_free xs (HOLogic.mk_eq (v, xctr))) xctrs xss;
    94 
   102 
    95     fun mk_caseof_args k xs x T =
   103     fun mk_sel_caseof_args k xs x T =
    96       map2 (fn Ts => fn i => if i = k then fold_rev Term.lambda xs x else mk_undef T Ts) ctr_Tss ks;
   104       map2 (fn Ts => fn i => if i = k then fold_rev Term.lambda xs x else mk_undef T Ts) ctr_Tss ks;
    97 
   105 
    98     fun disc_spec b exist_xs_v_eq_ctr =
   106     fun disc_spec b exist_xs_v_eq_ctr =
    99       HOLogic.mk_Trueprop (HOLogic.mk_eq (Free (Binding.name_of b, T --> HOLogic.boolT) $ v,
   107       mk_Trueprop_eq (Free (Binding.name_of b, T --> HOLogic.boolT) $ v, exist_xs_v_eq_ctr);
   100         exist_xs_v_eq_ctr));
       
   101 
   108 
   102     fun sel_spec b x xs k =
   109     fun sel_spec b x xs k =
   103       let val T' = fastype_of x in
   110       let val T' = fastype_of x in
   104         HOLogic.mk_Trueprop (HOLogic.mk_eq (Free (Binding.name_of b, T --> T') $ v,
   111         mk_Trueprop_eq (Free (Binding.name_of b, T --> T') $ v,
   105             Term.list_comb (mk_caseof As T', mk_caseof_args k xs x T') $ v))
   112           Term.list_comb (mk_caseof As T', mk_sel_caseof_args k xs x T') $ v)
   106       end;
   113       end;
   107 
   114 
   108     val (((raw_discs, (_, raw_disc_defs)), (raw_selss, (_, raw_sel_defss))), (lthy', lthy)) =
   115     val (((raw_discs, (_, raw_disc_defs)), (raw_selss, (_, raw_sel_defss))), (lthy', lthy)) =
   109       no_defs_lthy
   116       no_defs_lthy
   110       |> apfst (apsnd split_list o split_list) o fold_map2 (fn b => fn exist_xs_v_eq_ctr =>
   117       |> apfst (apsnd split_list o split_list) o fold_map2 (fn b => fn exist_xs_v_eq_ctr =>
   129       Term.subst_atomic_types (snd (dest_Type (domain_type (fastype_of t))) ~~ Ts) t;
   136       Term.subst_atomic_types (snd (dest_Type (domain_type (fastype_of t))) ~~ Ts) t;
   130 
   137 
   131     val discs = map (mk_disc_or_sel As) discs0;
   138     val discs = map (mk_disc_or_sel As) discs0;
   132     val selss = map (map (mk_disc_or_sel As)) selss0;
   139     val selss = map (map (mk_disc_or_sel As)) selss0;
   133 
   140 
   134     fun mk_imp_p Q = Logic.list_implies (Q, HOLogic.mk_Trueprop p);
   141     fun mk_imp_p Qs = Logic.list_implies (Qs, HOLogic.mk_Trueprop p);
   135 
   142 
   136     val goal_exhaust =
   143     val goal_exhaust =
   137       let
   144       let fun mk_prem xctr xs = fold_rev Logic.all xs (mk_imp_p [mk_Trueprop_eq (v, xctr)]) in
   138         fun mk_prem xctr xs =
       
   139           fold_rev Logic.all xs (mk_imp_p [HOLogic.mk_Trueprop (HOLogic.mk_eq (v, xctr))]);
       
   140       in
       
   141         mk_imp_p (map2 mk_prem xctrs xss)
   145         mk_imp_p (map2 mk_prem xctrs xss)
   142       end;
   146       end;
   143 
   147 
   144     val goal_injects =
   148     val goal_injects =
   145       let
   149       let
   146         fun mk_goal _ _ [] [] = NONE
   150         fun mk_goal _ _ [] [] = NONE
   147           | mk_goal xctr yctr xs ys =
   151           | mk_goal xctr yctr xs ys =
   148             SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq
   152             SOME (mk_Trueprop_eq (HOLogic.mk_eq (xctr, yctr),
   149               (HOLogic.mk_eq (xctr, yctr),
   153               Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys)));
   150                Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))));
       
   151       in
   154       in
   152         map_filter I (map4 mk_goal xctrs yctrs xss yss)
   155         map_filter I (map4 mk_goal xctrs yctrs xss yss)
   153       end;
   156       end;
   154 
   157 
   155     val goal_half_distincts =
   158     val goal_half_distincts =
   156       map (HOLogic.mk_Trueprop o HOLogic.mk_not o HOLogic.mk_eq) (mk_half_pairs xctrs);
   159       map (HOLogic.mk_Trueprop o HOLogic.mk_not o HOLogic.mk_eq) (mk_half_pairs xctrs);
   157 
   160 
   158     val goal_cases =
   161     val goal_cases =
   159       let
   162       let
   160         val lhs0 = Term.list_comb (caseofB, eta_fs);
   163         val lhs0 = Term.list_comb (caseofB, eta_fs);
   161         fun mk_goal xctr xs f =
   164         fun mk_goal xctr xs f = mk_Trueprop_eq (lhs0 $ xctr, Term.list_comb (f, xs));
   162           HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs0 $ xctr, Term.list_comb (f, xs)));
       
   163       in
   165       in
   164         map3 mk_goal xctrs xss fs
   166         map3 mk_goal xctrs xss fs
   165       end;
   167       end;
   166 
   168 
   167     val goals = [[goal_exhaust], goal_injects, goal_half_distincts, goal_cases];
   169     val goals = [[goal_exhaust], goal_injects, goal_half_distincts, goal_cases];
   168 
   170 
   169     fun after_qed thmss lthy =
   171     fun after_qed thmss lthy =
   170       let
   172       let
   171         val [[exhaust_thm], inject_thms, half_distinct_thms, case_thms] = thmss;
   173         val [[exhaust_thm], inject_thms, half_distinct_thms, case_thms] = thmss;
       
   174 
       
   175         val exhaust_thm' =
       
   176           let val Tinst = map (pairself (certifyT lthy)) (map Logic.varifyT_global As ~~ As) in
       
   177             Drule.instantiate' [] [SOME (certify lthy v)]
       
   178               (Thm.instantiate (Tinst, []) (Drule.zero_var_indexes exhaust_thm))
       
   179           end;
   172 
   180 
   173         val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
   181         val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
   174 
   182 
   175         val nchotomy_thm =
   183         val nchotomy_thm =
   176           let
   184           let
   187               let
   195               let
   188                 val T = fastype_of x;
   196                 val T = fastype_of x;
   189                 val cTs =
   197                 val cTs =
   190                   map ((fn T' => certifyT lthy (if T' = B then T else T')) o TFree)
   198                   map ((fn T' => certifyT lthy (if T' = B then T else T')) o TFree)
   191                     (rev (Term.add_tfrees goal_case []));
   199                     (rev (Term.add_tfrees goal_case []));
   192                 val cxs = map (certify lthy) (mk_caseof_args k xs x T);
   200                 val cxs = map (certify lthy) (mk_sel_caseof_args k xs x T);
   193               in
   201               in
   194                 Local_Defs.fold lthy [sel_def]
   202                 Local_Defs.fold lthy [sel_def]
   195                   (Drule.instantiate' (map SOME cTs) (map SOME cxs) case_thm)
   203                   (Drule.instantiate' (map SOME cTs) (map SOME cxs) case_thm)
   196               end;
   204               end;
   197             fun mk_thms k xs goal_case case_thm sel_defs =
   205             fun mk_thms k xs goal_case case_thm sel_defs =
   253 
   261 
   254         val ctr_sel_thms =
   262         val ctr_sel_thms =
   255           let
   263           let
   256             fun mk_goal ctr disc sels =
   264             fun mk_goal ctr disc sels =
   257               Logic.all v (Logic.mk_implies (HOLogic.mk_Trueprop (disc $ v),
   265               Logic.all v (Logic.mk_implies (HOLogic.mk_Trueprop (disc $ v),
   258                 HOLogic.mk_Trueprop (HOLogic.mk_eq ((null sels ? swap)
   266                 mk_Trueprop_eq ((null sels ? swap)
   259                   (Term.list_comb (ctr, map (fn sel => sel $ v) sels), v)))));
   267                   (Term.list_comb (ctr, map (fn sel => sel $ v) sels), v))));
   260             val goals = map3 mk_goal ctrs discs selss;
   268             val goals = map3 mk_goal ctrs discs selss;
   261           in
   269           in
   262             map4 (fn goal => fn m => fn discD => fn sel_thms =>
   270             map4 (fn goal => fn m => fn discD => fn sel_thms =>
   263               Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   271               Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   264                 mk_ctr_sel_tac ctxt m discD sel_thms))
   272                 mk_ctr_sel_tac ctxt m discD sel_thms))
   273                 Const (@{const_name If}, HOLogic.boolT --> B --> B --> B) $
   281                 Const (@{const_name If}, HOLogic.boolT --> B --> B --> B) $
   274                   (disc $ v) $ mk_core f sels $ mk_rhs discs fs selss;
   282                   (disc $ v) $ mk_core f sels $ mk_rhs discs fs selss;
   275 
   283 
   276             val lhs = Term.list_comb (caseofB, eta_fs) $ v;
   284             val lhs = Term.list_comb (caseofB, eta_fs) $ v;
   277             val rhs = mk_rhs discs fs selss;
   285             val rhs = mk_rhs discs fs selss;
   278             val goal = HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs, rhs));
   286             val goal = mk_Trueprop_eq (lhs, rhs);
   279 
       
   280             val Tinst = map (pairself (certifyT lthy)) (map Logic.varifyT_global As ~~ As);
       
   281             val exhaust_thm' =
       
   282               Drule.instantiate' [] [SOME (certify lthy v)]
       
   283                 (Thm.instantiate (Tinst, []) (Drule.zero_var_indexes exhaust_thm));
       
   284           in
   287           in
   285             Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   288             Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
   286               mk_case_disc_tac ctxt exhaust_thm' case_thms disc_thms sel_thmss)
   289               mk_case_disc_tac ctxt exhaust_thm' case_thms disc_thms sel_thmss)
   287             |> singleton (Proof_Context.export names_lthy lthy)
   290             |> singleton (Proof_Context.export names_lthy lthy)
   288           end;
   291           end;
   289 
   292 
   290         val case_cong_thm = TrueI;
   293         val case_cong_thm =
       
   294           let
       
   295             fun mk_prem xctr xs f g =
       
   296               fold_rev Logic.all xs (Logic.mk_implies (mk_Trueprop_eq (v, xctr),
       
   297                 mk_Trueprop_eq (f, g)));
       
   298             fun mk_caseof_term fs v = Term.list_comb (caseofB, fs) $ v;
       
   299 
       
   300             val goal =
       
   301               Logic.list_implies (mk_Trueprop_eq (v, w) :: map4 mk_prem xctrs xss fs gs,
       
   302                  mk_Trueprop_eq (mk_caseof_term eta_fs v, mk_caseof_term eta_gs w));
       
   303           in
       
   304             Skip_Proof.prove lthy [] [] goal (fn {context = ctxt, ...} =>
       
   305               mk_case_cong_tac ctxt exhaust_thm' case_thms)
       
   306             |> singleton (Proof_Context.export names_lthy lthy)
       
   307           end;
   291 
   308 
   292         val weak_case_cong_thms = TrueI;
   309         val weak_case_cong_thms = TrueI;
   293 
   310 
   294         val split_thms = [];
   311         val split_thms = [];
   295 
   312