src/HOL/Codatatype/Tools/bnf_sugar.ML
changeset 49020 f379cf5d71bd
parent 49019 fc4decdba5ce
child 49022 005ce926a932
equal deleted inserted replaced
49019:fc4decdba5ce 49020:f379cf5d71bd
    12 structure BNF_Sugar : BNF_SUGAR =
    12 structure BNF_Sugar : BNF_SUGAR =
    13 struct
    13 struct
    14 
    14 
    15 open BNF_Util
    15 open BNF_Util
    16 open BNF_FP_Util
    16 open BNF_FP_Util
       
    17 open BNF_Sugar_Tactics
    17 
    18 
    18 val distinctN = "distinct";
    19 val distinctN = "distinct";
    19 
    20 
    20 fun prepare_sugar prep_typ prep_term ((((raw_T, raw_ctors), raw_dtors), raw_storss), raw_recur)
    21 fun prepare_sugar prep_term (((raw_ctors, raw_dtors), raw_storss), raw_recur)
    21   lthy =
    22   lthy =
    22   let
    23   let
    23     (* TODO: sanity checks on arguments *)
    24     (* TODO: sanity checks on arguments *)
    24 
    25 
    25     val T as Type (T_name, _) = prep_typ lthy raw_T;
       
    26     val b = Binding.qualified_name T_name;
       
    27 
       
    28     val ctors = map (prep_term lthy) raw_ctors;
    26     val ctors = map (prep_term lthy) raw_ctors;
    29     val ctor_Tss = map (binder_types o fastype_of) ctors;
    27     val ctor_Tss = map (binder_types o fastype_of) ctors;
    30 
    28 
    31     val ((xss, yss), _) = lthy |>
    29     val T as Type (T_name, _) = body_type (fastype_of (hd ctors));
       
    30     val b = Binding.qualified_name T_name;
       
    31 
       
    32     val n = length ctors;
       
    33 
       
    34     val ((((xss, yss), (v, v')), p), _) = lthy |>
    32       mk_Freess "x" ctor_Tss
    35       mk_Freess "x" ctor_Tss
    33       ||>> mk_Freess "y" ctor_Tss;
    36       ||>> mk_Freess "y" ctor_Tss
       
    37       ||>> yield_singleton (apfst (op ~~) oo mk_Frees' "v") T
       
    38       ||>> yield_singleton (mk_Frees "P") HOLogic.boolT;
       
    39 
       
    40     val xs_ctors = map2 (curry Term.list_comb) ctors xss;
       
    41     val ys_ctors = map2 (curry Term.list_comb) ctors yss;
       
    42 
       
    43     val goal_exhaust =
       
    44       let
       
    45         fun mk_imp_p Q = Logic.list_implies (Q, HOLogic.mk_Trueprop p);
       
    46         fun mk_prem xs_ctor xs =
       
    47           fold_rev Logic.all xs
       
    48             (mk_imp_p [HOLogic.mk_Trueprop (HOLogic.mk_eq (v, xs_ctor))]);
       
    49       in
       
    50         mk_imp_p (map2 mk_prem xs_ctors xss)
       
    51       end;
    34 
    52 
    35     val goal_injects =
    53     val goal_injects =
    36       let
    54       let
    37         fun mk_goal _ [] [] = NONE
    55         fun mk_goal _ _ [] [] = NONE
    38           | mk_goal ctor xs ys =
    56           | mk_goal xs_ctor ys_ctor xs ys =
    39             SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq
    57             SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq
    40               (HOLogic.mk_eq (Term.list_comb (ctor, xs), Term.list_comb (ctor, ys)),
    58               (HOLogic.mk_eq (xs_ctor, ys_ctor),
    41                Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))));
    59                Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))));
    42       in
    60       in
    43         map_filter I (map3 mk_goal ctors xss yss)
    61         map_filter I (map4 mk_goal xs_ctors ys_ctors xss yss)
    44       end;
    62       end;
    45 
    63 
    46     val goal_half_distincts =
    64     val goal_half_distincts =
    47       let
    65       let
    48         fun mk_goal t u = HOLogic.mk_Trueprop (HOLogic.mk_not (HOLogic.mk_eq (t, u)));
    66         fun mk_goal t u = HOLogic.mk_Trueprop (HOLogic.mk_not (HOLogic.mk_eq (t, u)));
    49         fun mk_goals [] = []
    67         fun mk_goals [] = []
    50           | mk_goals (t :: ts) = fold_rev (cons o mk_goal t) ts (mk_goals ts);
    68           | mk_goals (t :: ts) = fold_rev (cons o mk_goal t) ts (mk_goals ts);
    51       in
    69       in
    52         mk_goals (map2 (curry Term.list_comb) ctors xss)
    70         mk_goals xs_ctors
    53       end;
    71       end;
    54 
    72 
    55     val goals = [goal_injects, goal_half_distincts];
    73     val goals = [[goal_exhaust], goal_injects, goal_half_distincts];
    56 
    74 
    57     fun after_qed thmss lthy =
    75     fun after_qed thmss lthy =
    58       let
    76       let
    59         val [inject_thms, half_distinct_thms] = thmss;
    77         val [[exhaust_thm], inject_thms, half_distinct_thms] = thmss;
    60 
    78 
    61         val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
    79         val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
       
    80 
       
    81         val nchotomy_thm =
       
    82           let
       
    83             fun mk_disjunct xs_ctor xs = list_exists_free xs (HOLogic.mk_eq (v, xs_ctor))
       
    84             val goal =
       
    85               HOLogic.mk_Trueprop
       
    86                 (HOLogic.mk_all (fst v', snd v',
       
    87                    Library.foldr1 HOLogic.mk_disj (map2 mk_disjunct xs_ctors xss)));
       
    88           in
       
    89             Skip_Proof.prove lthy [] [] goal (fn _ => mk_nchotomy_tac n exhaust_thm)
       
    90           end;
    62 
    91 
    63         fun note thmN thms =
    92         fun note thmN thms =
    64           snd o Local_Theory.note
    93           snd o Local_Theory.note
    65             ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), thms);
    94             ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), thms);
    66       in
    95       in
    67         lthy
    96         lthy
       
    97         |> note distinctN (half_distinct_thms @ other_half_distinct_thms)
       
    98         |> note exhaustN [exhaust_thm]
    68         |> note injectN inject_thms
    99         |> note injectN inject_thms
    69         |> note distinctN (half_distinct_thms @ other_half_distinct_thms)
   100         |> note nchotomyN [nchotomy_thm]
    70       end;
   101       end;
    71   in
   102   in
    72     (goals, after_qed, lthy)
   103     (goals, after_qed, lthy)
    73   end;
   104   end;
    74 
   105 
    75 val parse_binding_list = Parse.$$$ "[" |--  Parse.list Parse.binding --| Parse.$$$ "]";
   106 val parse_binding_list = Parse.$$$ "[" |--  Parse.list Parse.binding --| Parse.$$$ "]";
    76 
   107 
    77 val bnf_sugar_cmd = (fn (goalss, after_qed, lthy) =>
   108 val bnf_sugar_cmd = (fn (goalss, after_qed, lthy) =>
    78   Proof.theorem NONE after_qed (map (map (rpair [])) goalss) lthy) oo
   109   Proof.theorem NONE after_qed (map (map (rpair [])) goalss) lthy) oo
    79   prepare_sugar Syntax.read_typ Syntax.read_term;
   110   prepare_sugar Syntax.read_term;
    80 
   111 
    81 val _ =
   112 val _ =
    82   Outer_Syntax.local_theory_to_proof @{command_spec "bnf_sugar"} "adds sugar on top of a BNF"
   113   Outer_Syntax.local_theory_to_proof @{command_spec "bnf_sugar"} "adds sugar on top of a BNF"
    83     ((Parse.typ -- (Parse.$$$ "[" |-- Parse.list Parse.term --| Parse.$$$ "]") --
   114     (((Parse.$$$ "[" |-- Parse.list Parse.term --| Parse.$$$ "]") --
    84       parse_binding_list -- (Parse.$$$ "[" |-- Parse.list parse_binding_list --| Parse.$$$ "]") --
   115       parse_binding_list -- (Parse.$$$ "[" |-- Parse.list parse_binding_list --| Parse.$$$ "]") --
    85       Parse.term) >> bnf_sugar_cmd);
   116       Parse.term) >> bnf_sugar_cmd);
    86 
   117 
    87 end;
   118 end;