signature DATATYPE_TACTICS = sig val exhaust_tac: Proof.context -> string -> (binding * stringoption * mixfix) list ->
int -> tactic val induct_tac: Proof.context -> string -> (binding * stringoption * mixfix) list ->
int -> tactic val rep_datatype_i: thm -> thm -> thm list -> thm list -> theory -> theory val rep_datatype: Facts.ref * Token.src list -> Facts.ref * Token.src list ->
(Facts.ref * Token.src list) list -> (Facts.ref * Token.src list) list -> theory -> theory end;
(** Datatype information, e.g. associated theorems **)
type datatype_info =
{inductive: bool, (*true if inductive, not coinductive*)
constructors : term list, (*the constructors, as Consts*)
rec_rewrites : thm list, (*recursor equations*)
case_rewrites : thm list, (*case equations*)
induct : thm,
mutual_induct : thm,
exhaustion : thm};
structure DatatypesData = Theory_Data
( type T = datatype_info Symtab.table; val empty = Symtab.empty; fun merge data : T = Symtab.merge (K true) data;
);
(** Constructor information: needed to map constructors to datatypes **)
type constructor_info =
{big_rec_name : string, (*name of the mutually recursive set*)
constructors : term list, (*the constructors, as Consts*)
free_iffs : thm list, (*freeness simprules*)
rec_rewrites : thm list}; (*recursor equations*)
structure ConstructorsData = Theory_Data
( type T = constructor_info Symtab.table val empty = Symtab.empty fun merge data = Symtab.merge (K true) data;
);
fun datatype_info thy name =
(case Symtab.lookup (DatatypesData.get thy) name of
SOME info => info
| NONE => error ("Unknown datatype " ^ quote name));
(*Given a variable, find the inductive set associated it in the assumptions*)
exception Find_tname ofstring
fun find_tname ctxt var As = letfun mk_pair \<^Const_>\<open>mem for \<open>Free (v,_)\<close> A\<close> = (v, dest_Const_name (head_of A))
| mk_pair _ = raiseMatch val pairs = map_filter (try (mk_pair o \<^dest_judgment>)) As val x =
(casetry (dest_Free o Syntax.read_term ctxt) var of
SOME (x, _) => x
| _ => raise Find_tname ("Bad variable " ^ quote var)) incase AList.lookup (op =) pairs x of
NONE => raise Find_tname ("Cannot determine datatype of " ^ quote var)
| SOME t => t end;
(** generic exhaustion and induction tactic for datatypes DifferencesfromHOL: (1)nocheckingiftheinductionvaroccursinpremises,sinceitalways appearsinoneofthem,andit'shardtocheckforotheroccurrences (2)exhaustionworksforVARIABLESinthepremises,notgeneralterms
**)
fun exhaust_induct_tac exh ctxt var fixes i state = SUBGOAL (fn _ => let val thy = Proof_Context.theory_of ctxt val ({context = ctxt', asms, ...}, _) = Subgoal.focus ctxt i NONE state val tn = find_tname ctxt' var (map Thm.term_of asms) val rule =
datatype_info thy tn
|> (if exh then #exhaustion else #induct)
|> Thm.transfer thy; val \<^Const_>\<open>mem for \<open>Var(ixn,_)\<close> _\<close> =
(case Thm.take_prems_of 1 rule of
[] => error "induction is not available for this datatype"
| major::_ => \<^dest_judgment> major) in
Rule_Insts.eres_inst_tac ctxt [((ixn, Position.none), var)] fixes rule i end handle Find_tname msg => if exh then(*try boolean case analysis instead*)
case_tac ctxt var fixes i else error msg) i state;
val exhaust_tac = exhaust_induct_tac true; val induct_tac = exhaust_induct_tac false;
(**** declare non-datatype as datatype ****)
fun rep_datatype_i elim induct case_eqns recursor_eqns thy = let (*analyze the LHS of a case equation to get a constructor*) fun const_of \<^Const_>\<open>IFOL.eq _ for \<open>_ $ c\<close> _\<close> = c
| const_of eqn = error ("Ill-formed case equation: " ^
Syntax.string_of_term_global thy eqn);
val constructors = map (head_of o const_of o \<^dest_judgment> o Thm.prop_of) case_eqns;
val \<^Const_>\<open>mem for _ data\<close> = \<^dest_judgment> (hd (Thm.take_prems_of 1 elim));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.