src/HOL/Codatatype/Tools/bnf_sugar.ML
changeset 49019 fc4decdba5ce
parent 49017 66fc7fc2d49b
child 49020 f379cf5d71bd
--- a/src/HOL/Codatatype/Tools/bnf_sugar.ML	Thu Aug 30 09:47:46 2012 +0200
+++ b/src/HOL/Codatatype/Tools/bnf_sugar.ML	Thu Aug 30 09:47:46 2012 +0200
@@ -7,43 +7,76 @@
 
 signature BNF_SUGAR =
 sig
-  val prepare_sugar : (Proof.context -> 'b -> term) ->
-    (((typ * 'b list) * binding list) * binding list list) * 'b -> local_theory ->
-    term list * local_theory
 end;
 
 structure BNF_Sugar : BNF_SUGAR =
 struct
 
 open BNF_Util
+open BNF_FP_Util
 
-fun prepare_sugar prep_term ((((raw_T, raw_ctors), raw_dtors), raw_storss), raw_recur) lthy =
+val distinctN = "distinct";
+
+fun prepare_sugar prep_typ prep_term ((((raw_T, raw_ctors), raw_dtors), raw_storss), raw_recur)
+  lthy =
   let
-    val ctors = map (prep_term lthy) raw_ctors;
+    (* TODO: sanity checks on arguments *)
 
-    (* TODO: sanity checks on arguments *)
+    val T as Type (T_name, _) = prep_typ lthy raw_T;
+    val b = Binding.qualified_name T_name;
+
+    val ctors = map (prep_term lthy) raw_ctors;
     val ctor_Tss = map (binder_types o fastype_of) ctors;
-    val (ctor_argss, _) = lthy |>
-      mk_Freess "x" ctor_Tss;
 
-    val goal_distincts =
+    val ((xss, yss), _) = lthy |>
+      mk_Freess "x" ctor_Tss
+      ||>> mk_Freess "y" ctor_Tss;
+
+    val goal_injects =
       let
-        fun mk_goal t u = HOLogic.mk_Trueprop (HOLogic.mk_not (HOLogic.mk_eq (t, u)))
-        fun mk_goals [] = []
-          | mk_goals (t :: ts) = fold_rev (cons o mk_goal t) ts (mk_goals ts)
+        fun mk_goal _ [] [] = NONE
+          | mk_goal ctor xs ys =
+            SOME (HOLogic.mk_Trueprop (HOLogic.mk_eq
+              (HOLogic.mk_eq (Term.list_comb (ctor, xs), Term.list_comb (ctor, ys)),
+               Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) xs ys))));
       in
-        mk_goals (map2 (curry Term.list_comb) ctors ctor_argss)
+        map_filter I (map3 mk_goal ctors xss yss)
       end;
 
-    val goals = goal_distincts;
+    val goal_half_distincts =
+      let
+        fun mk_goal t u = HOLogic.mk_Trueprop (HOLogic.mk_not (HOLogic.mk_eq (t, u)));
+        fun mk_goals [] = []
+          | mk_goals (t :: ts) = fold_rev (cons o mk_goal t) ts (mk_goals ts);
+      in
+        mk_goals (map2 (curry Term.list_comb) ctors xss)
+      end;
+
+    val goals = [goal_injects, goal_half_distincts];
+
+    fun after_qed thmss lthy =
+      let
+        val [inject_thms, half_distinct_thms] = thmss;
+
+        val other_half_distinct_thms = map (fn thm => thm RS not_sym) half_distinct_thms;
+
+        fun note thmN thms =
+          snd o Local_Theory.note
+            ((Binding.qualify true (Binding.name_of b) (Binding.name thmN), []), thms);
+      in
+        lthy
+        |> note injectN inject_thms
+        |> note distinctN (half_distinct_thms @ other_half_distinct_thms)
+      end;
   in
-    (goals, lthy)
+    (goals, after_qed, lthy)
   end;
 
 val parse_binding_list = Parse.$$$ "[" |--  Parse.list Parse.binding --| Parse.$$$ "]";
 
-val bnf_sugar_cmd = (fn (goals, lthy) =>
-  Proof.theorem NONE (K I) (map (single o rpair []) goals) lthy) oo prepare_sugar Syntax.read_term;
+val bnf_sugar_cmd = (fn (goalss, after_qed, lthy) =>
+  Proof.theorem NONE after_qed (map (map (rpair [])) goalss) lthy) oo
+  prepare_sugar Syntax.read_typ Syntax.read_term;
 
 val _ =
   Outer_Syntax.local_theory_to_proof @{command_spec "bnf_sugar"} "adds sugar on top of a BNF"