src/HOL/Tools/induct_method.ML
author wenzelm
Fri, 16 Apr 1999 14:50:30 +0200
changeset 6442 6a95ceaa977e
child 6446 583add9799c3
permissions -rw-r--r--
Proof by induction on types / set / functions.

(*  Title:      HOL/Tools/induct_method.ML
    ID:         $Id$
    Author:     Markus Wenzel, TU Muenchen

Proof by induction on types / set / functions.

TODO:
  - induct vs. coinduct (!?);
  - use of 'function' (!?);
*)

signature INDUCT_METHOD =
sig
  val setup: (theory -> theory) list
end;

structure InductMethod: INDUCT_METHOD =
struct


(* type induct_kind *)

datatype induct_kind = Type | Set | Function;

val typeN = "type";
val setN = "set";
val functionN = "function";

val kind =
  (Args.$$$ typeN >> K Type || Args.$$$ setN >> K Set || Args.$$$ functionN >> K Function)
    --| Args.$$$ ":";


(* 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 =
  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
          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;


(* induct_method *)

val term = Scan.unless (Scan.lift kind) Args.local_term;

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)));

fun induct_meth src ctxt = #2 (Method.syntax (induct ctxt) ctxt src);
val induct_method = ("induct", induct_meth, "induction on types / sets / functions");


(* theory setup *)

val setup = [Method.add_methods [induct_method]];


end;