src/HOL/Tools/function_package/inductive_wrap.ML
changeset 20523 36a59e5d0039
child 21025 10b0821a4d11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/function_package/inductive_wrap.ML	Wed Sep 13 12:05:50 2006 +0200
@@ -0,0 +1,110 @@
+(*  Title:      HOL/Tools/function_package/inductive_wrap.ML
+    ID:         $Id$
+    Author:     Alexander Krauss, TU Muenchen
+
+
+This is a wrapper around the inductive package which corrects some of its
+slightly annoying behaviours and makes the whole business more controllable.
+
+Specifically:
+
+- Following newer Isar conventions, declaration and definition are done in one step
+
+- The specification is expected in fully quantified form. This allows the client to 
+  control the variable order. The variables will appear in the result in the same order.
+  This is especially relevant for the elimination rule, where the order usually *does* matter.
+
+
+All this will probably become obsolete in the near future, when the new "predicate" package
+is in place.
+
+*)
+
+signature FUNDEF_INDUCTIVE_WRAP =
+sig
+  val inductive_def :  term list 
+                       -> ((bstring * typ) * mixfix) * local_theory
+                       -> thm list * (term * thm * local_theory)
+end
+
+structure FundefInductiveWrap =
+struct
+
+
+fun inst_forall (Free (n,_)) (_ $ Abs (_, T, b)) = subst_bound (Free (n, T), b)
+  | inst_forall t1 t2 = sys_error ((Sign.string_of_term (the_context ()) t1))
+
+fun permute_bounds_in_premises thy [] impl = impl
+  | permute_bounds_in_premises thy ((oldvs, newvs) :: perms) impl =
+    let
+      val (prem, concl) = dest_implies (cprop_of impl)
+
+      val newprem = term_of prem
+                      |> fold inst_forall oldvs
+                      |> fold_rev mk_forall newvs
+                      |> cterm_of thy
+    in
+      assume newprem
+             |> fold (forall_elim o cterm_of thy) newvs
+             |> fold_rev (forall_intr o cterm_of thy) oldvs
+             |> implies_elim impl
+             |> permute_bounds_in_premises thy perms
+             |> implies_intr newprem
+    end
+
+
+fun inductive_def defs (((R, T), mixfix), lthy) =
+    let
+      fun wrap1 thy =
+          let
+            val thy = Sign.add_consts_i [(R, T, mixfix)] thy
+            val RC = Const (Sign.full_name thy R, T)
+
+            val cdefs = map (Pattern.rewrite_term thy [(Free (R, T), RC)] []) defs
+            val qdefs = map dest_all_all cdefs
+
+            val (thy, {intrs = intrs_gen, elims = [elim_gen], ...}) =
+                InductivePackage.add_inductive_i true (*verbose*)
+                                                 false (* dont add_consts *)
+                                                 "" (* no altname *)
+                                                 false (* no coind *)
+                                                 false (* elims, please *)
+                                                 false (* induction thm please *)
+                                                 [RC] (* the constant *)
+                                                 (map (fn (_,t) => (("", t),[])) qdefs) (* the intros *)
+                                                 [] (* no special monos *)
+                                                 thy
+
+            val perms = map (fn (qs, t) => ((term_frees t) inter qs, qs)) qdefs
+
+            fun inst (qs, _) intr_gen =
+                intr_gen
+                  |> Thm.freezeT
+                  |> fold_rev (forall_intr o (fn Free (n, T) => cterm_of thy (Var ((n,0), T)))) qs
+
+
+            val a = cterm_of thy (Free ("a0123", HOLogic.dest_setT T)) (* Let's just hope there are no clashes :-} *)
+            val P = cterm_of thy (Free ("P0123", HOLogic.boolT))
+                
+            val intrs = map2 inst qdefs intrs_gen
+
+            val elim = elim_gen
+                         |> Thm.freezeT
+                         |> forall_intr_vars (* FIXME... *)
+                         |> forall_elim a
+                         |> forall_elim P
+                         |> permute_bounds_in_premises thy (([],[]) :: perms)
+                         |> forall_intr P
+                         |> forall_intr a
+          in
+            ((RC, (intrs, elim)), thy)
+          end
+
+      val ((RC, (intrs, elim)), lthy) = LocalTheory.theory_result wrap1 lthy
+    in
+      (intrs, (RC, elim, lthy))
+    end
+
+
+end
+