may specify induction predicates as well;
authorwenzelm
Fri, 16 Apr 1999 17:47:06 +0200
changeset 6446 583add9799c3
parent 6445 931fc1daa8b1
child 6447 83d8dabdae9a
may specify induction predicates as well;
src/HOL/Tools/induct_method.ML
--- a/src/HOL/Tools/induct_method.ML	Fri Apr 16 17:46:02 1999 +0200
+++ b/src/HOL/Tools/induct_method.ML	Fri Apr 16 17:47:06 1999 +0200
@@ -3,10 +3,6 @@
     Author:     Markus Wenzel, TU Muenchen
 
 Proof by induction on types / set / functions.
-
-TODO:
-  - induct vs. coinduct (!?);
-  - use of 'function' (!?);
 *)
 
 signature INDUCT_METHOD =
@@ -31,39 +27,52 @@
     --| Args.$$$ ":";
 
 
+(* induct_rule *)
+
+fun kind_rule Type = (#induction oo DatatypePackage.datatype_info, Sign.intern_tycon)
+  | kind_rule Set = ((#induct o #2) oo InductivePackage.get_inductive, Sign.intern_const)
+  | kind_rule Function = (#induct oo RecdefPackage.get_recdef, Sign.intern_const);
+
+fun induct_rule thy kind name =
+  let val (ind_rule, intern) = kind_rule kind
+  in ind_rule thy (intern (Theory.sign_of thy) name) end;
+
+
 (* induct_tac *)
 
-fun induct_rule thy Type name = #induction (DatatypePackage.datatype_info thy name)
-  | induct_rule thy Set name = #induct (#2 (InductivePackage.get_inductive thy name))
-  | induct_rule thy Function name = #induct (RecdefPackage.get_recdef thy name);
-
-
-fun induct_tac thy xs opt_kind_name i state =
+fun induct_tac thy insts opt_kind_name i state =
   let
     val (kind, name) =
       (case opt_kind_name of Some kind_name => kind_name | None =>
-        (case try (#1 o Term.dest_Type o Term.type_of o hd) xs of
+        (case try (#1 o Term.dest_Type o Term.type_of o #2 o hd) insts of
           Some name => (Type, name)
         | None => error "Unable to figure out induction rule"));
     val rule = Drule.incr_indexes_wrt [] [] [] [state] (induct_rule thy kind name);
 
-    fun inst_rule () =
-      let
-        val cert = Thm.cterm_of (Sign.merge (pairself Thm.sign_of_thm (state, rule)));
-        fun rule_var (_ $ x) = cert x
-          | rule_var _ = raise THM ("Malformed induction rule", 0, [rule]);
-        val rule_preds = DatatypeAux.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of rule));
-      in Drule.cterm_instantiate (map rule_var rule_preds ~~ map cert xs) rule end;
-  in Tactic.rtac (if null xs then rule else inst_rule ()) i state end;
+
+    val cert = Thm.cterm_of (Sign.merge (pairself Thm.sign_of_thm (state, rule)));
+
+    fun prep_inst ((P $ x), (Some Q, y)) = [(cert P, cert Q), (cert x, cert y)]
+      | prep_inst ((_ $ x), (None, y)) = [(cert x, cert y)]
+      | prep_inst _ = raise THM ("Malformed induction rule", 0, [rule]);
+
+    val prep_insts = flat o map2 prep_inst;
+
+    val inst_rule =
+      if null insts then rule
+      else Drule.cterm_instantiate (prep_insts
+        (DatatypeAux.dest_conj (HOLogic.dest_Trueprop (Thm.concl_of rule)), insts)) rule;
+  in Tactic.rtac inst_rule i state end;
 
 
 (* induct_method *)
 
 val term = Scan.unless (Scan.lift kind) Args.local_term;
+val inst = term -- term >> (apfst Some) || term >> pair None;
 
 fun induct ctxt =
-  Scan.repeat term -- Scan.option (Scan.lift (kind -- Args.name))
-  >> (fn (xs, k) => Method.METHOD0 (FIRSTGOAL (induct_tac (ProofContext.theory_of ctxt) xs k)));
+  Args.and_list inst -- Scan.option (Scan.lift (kind -- Args.name))
+  >> (fn (is, k) => Method.METHOD0 (FIRSTGOAL (induct_tac (ProofContext.theory_of ctxt) is k)));
 
 fun induct_meth src ctxt = #2 (Method.syntax (induct ctxt) ctxt src);
 val induct_method = ("induct", induct_meth, "induction on types / sets / functions");