wenzelm@404: (* Title: Pure/axclass.ML wenzelm@404: ID: $Id$ wenzelm@404: Author: Markus Wenzel, TU Muenchen wenzelm@404: wenzelm@423: Higher level user interfaces for axiomatic type classes. wenzelm@404: *) wenzelm@404: wenzelm@404: signature AX_CLASS = wenzelm@404: sig wenzelm@404: structure Tactical: TACTICAL wenzelm@423: local open Tactical Tactical.Thm Tactical.Thm.Sign.Syntax.Mixfix in wenzelm@423: val add_thms_as_axms: (string * thm) list -> theory -> theory wenzelm@423: val add_classrel_thms: thm list -> theory -> theory wenzelm@423: val add_arity_thms: thm list -> theory -> theory wenzelm@404: val add_axclass: class * class list -> (string * string) list wenzelm@404: -> theory -> theory wenzelm@404: val add_axclass_i: class * class list -> (string * term) list wenzelm@404: -> theory -> theory wenzelm@423: val add_sigclass: class * class list -> (string * string * mixfix) list wenzelm@423: -> theory -> theory wenzelm@423: val add_sigclass_i: class * class list -> (string * typ * mixfix) list wenzelm@423: -> theory -> theory wenzelm@423: val axclass_tac: theory -> thm list -> tactic wenzelm@423: val prove_classrel: theory -> class * class -> thm list wenzelm@423: -> tactic option -> thm wenzelm@423: val prove_arity: theory -> string * sort list * class -> thm list wenzelm@423: -> tactic option -> thm wenzelm@423: val add_subclass: class * class -> string list -> thm list wenzelm@404: -> tactic option -> theory -> theory wenzelm@423: val add_instance: string * sort list * class list -> string list wenzelm@423: -> thm list -> tactic option -> theory -> theory wenzelm@404: end wenzelm@404: end; wenzelm@404: wenzelm@404: functor AxClassFun(structure Logic: LOGIC and Goals: GOALS and Tactic: TACTIC wenzelm@404: sharing Goals.Tactical = Tactic.Tactical)(*: AX_CLASS *) = (* FIXME *) wenzelm@404: struct wenzelm@404: wenzelm@404: structure Tactical = Goals.Tactical; wenzelm@404: structure Thm = Tactical.Thm; wenzelm@404: structure Sign = Thm.Sign; wenzelm@404: structure Type = Sign.Type; wenzelm@404: wenzelm@404: open Logic Thm Tactical Tactic Goals; wenzelm@404: wenzelm@404: wenzelm@423: (* FIXME fake! - remove *) wenzelm@404: wenzelm@404: val add_defns = add_axioms; wenzelm@404: val add_defns_i = add_axioms_i; wenzelm@404: wenzelm@404: wenzelm@423: wenzelm@404: (** utilities **) wenzelm@404: wenzelm@404: (* type vars *) wenzelm@404: wenzelm@404: fun map_typ_frees f (Type (t, tys)) = Type (t, map (map_typ_frees f) tys) wenzelm@404: | map_typ_frees f (TFree a) = f a wenzelm@404: | map_typ_frees _ a = a; wenzelm@404: wenzelm@404: val map_term_tfrees = map_term_types o map_typ_frees; wenzelm@404: wenzelm@404: fun aT S = TFree ("'a", S); wenzelm@404: wenzelm@404: wenzelm@404: (* get axioms *) wenzelm@404: wenzelm@404: fun get_ax thy name = wenzelm@404: Some (get_axiom thy name) handle THEORY _ => None; wenzelm@404: wenzelm@404: val get_axioms = mapfilter o get_ax; wenzelm@404: wenzelm@404: wenzelm@404: (* is_defn *) wenzelm@404: wenzelm@404: fun is_defn thm = wenzelm@404: (case #prop (rep_thm thm) of wenzelm@404: Const ("==", _) $ _ $ _ => true wenzelm@404: | _ => false); wenzelm@404: wenzelm@404: wenzelm@404: wenzelm@423: (** abstract syntax operations **) (* FIXME -> logic.ML (?) *) wenzelm@423: wenzelm@423: (* subclass relations as terms *) wenzelm@423: wenzelm@423: fun mk_classrel (c1, c2) = mk_inclass (aT [c1], c2); wenzelm@423: wenzelm@423: fun dest_classrel tm = wenzelm@423: let wenzelm@423: fun err () = raise_term "dest_classrel" [tm]; wenzelm@423: wenzelm@423: val (ty, c2) = dest_inclass (freeze_vars tm) handle TERM _ => err (); wenzelm@423: val c1 = (case ty of TFree (_, [c]) => c | _ => err ()); wenzelm@423: in wenzelm@423: (c1, c2) wenzelm@423: end; wenzelm@423: wenzelm@423: wenzelm@423: (* arities as terms *) wenzelm@423: wenzelm@423: fun mk_arity (t, ss, c) = wenzelm@423: let wenzelm@423: val names = variantlist (replicate (length ss) "'a", []); wenzelm@423: val tfrees = map TFree (names ~~ ss); wenzelm@423: in wenzelm@423: mk_inclass (Type (t, tfrees), c) wenzelm@423: end; wenzelm@423: wenzelm@423: fun dest_arity tm = wenzelm@423: let wenzelm@423: fun err () = raise_term "dest_arity" [tm]; wenzelm@423: wenzelm@423: val (ty, c) = dest_inclass (freeze_vars tm) handle TERM _ => err (); wenzelm@423: val (t, tfrees) = wenzelm@423: (case ty of wenzelm@423: Type (t, tys) => (t, map (fn TFree x => x | _ => err ()) tys) wenzelm@423: | _ => err ()); wenzelm@423: val ss = wenzelm@423: if null (gen_duplicates eq_fst tfrees) wenzelm@423: then map snd tfrees else err (); wenzelm@423: in wenzelm@423: (t, ss, c) wenzelm@423: end; wenzelm@423: wenzelm@423: wenzelm@423: wenzelm@423: (** add theorems as axioms **) (* FIXME -> drule.ML (?) *) wenzelm@423: wenzelm@423: fun prep_thm_axm thy thm = wenzelm@423: let wenzelm@423: fun err msg = raise THM ("prep_thm_axm: " ^ msg, 0, [thm]); wenzelm@423: wenzelm@423: val {sign, hyps, prop, ...} = rep_thm thm; wenzelm@423: in wenzelm@423: if not (Sign.subsig (sign, sign_of thy)) then wenzelm@423: err "theorem not of same theory" wenzelm@423: else if not (null hyps) then wenzelm@423: err "theorem may not contain hypotheses" wenzelm@423: else prop wenzelm@423: end; wenzelm@423: wenzelm@423: (*general theorems*) wenzelm@423: fun add_thms_as_axms thms thy = wenzelm@423: add_axioms_i (map (apsnd (prep_thm_axm thy)) thms) thy; wenzelm@423: wenzelm@423: (*theorems expressing class relations*) wenzelm@423: fun add_classrel_thms thms thy = wenzelm@423: let wenzelm@423: fun prep_thm thm = wenzelm@423: let wenzelm@423: val prop = prep_thm_axm thy thm; wenzelm@423: val (c1, c2) = dest_classrel prop handle TERM _ => wenzelm@423: raise THM ("add_classrel_thms: theorem is not a class relation", 0, [thm]); wenzelm@423: in (c1, c2) end; wenzelm@423: in wenzelm@423: add_classrel (map prep_thm thms) thy wenzelm@423: end; wenzelm@423: wenzelm@423: (*theorems expressing arities*) wenzelm@423: fun add_arity_thms thms thy = wenzelm@423: let wenzelm@423: fun prep_thm thm = wenzelm@423: let wenzelm@423: val prop = prep_thm_axm thy thm; wenzelm@423: val (t, ss, c) = dest_arity prop handle TERM _ => wenzelm@423: raise THM ("add_arity_thms: theorem is not an arity", 0, [thm]); wenzelm@423: in (t, ss, [c]) end; wenzelm@423: in wenzelm@423: add_arities (map prep_thm thms) thy wenzelm@423: end; wenzelm@423: wenzelm@423: wenzelm@423: wenzelm@423: (** add axiomatic type classes **) wenzelm@404: wenzelm@404: (* errors *) wenzelm@404: wenzelm@404: fun err_not_logic c = wenzelm@404: error ("Axiomatic class " ^ quote c ^ " not subclass of \"logic\""); wenzelm@404: wenzelm@404: fun err_bad_axsort ax c = wenzelm@404: error ("Sort constraint in axiom " ^ quote ax ^ " not supersort of " ^ quote c); wenzelm@404: wenzelm@404: fun err_bad_tfrees ax = wenzelm@404: error ("More than one type variable in axiom " ^ quote ax); wenzelm@404: wenzelm@404: wenzelm@404: (* ext_axclass *) wenzelm@404: wenzelm@404: fun ext_axclass prep_axm (class, super_classes) raw_axioms old_thy = wenzelm@404: let wenzelm@404: val axioms = map (prep_axm (sign_of old_thy)) raw_axioms; wenzelm@404: val thy = add_classes [([], class, super_classes)] old_thy; wenzelm@404: val sign = sign_of thy; wenzelm@404: wenzelm@404: wenzelm@404: (* prepare abstract axioms *) wenzelm@404: wenzelm@404: fun abs_axm ax = wenzelm@404: if null (term_tfrees ax) then wenzelm@404: mk_implies (mk_inclass (aT logicS, class), ax) wenzelm@404: else wenzelm@404: map_term_tfrees (K (aT [class])) ax; wenzelm@404: wenzelm@404: val abs_axioms = map (apsnd abs_axm) axioms; wenzelm@404: wenzelm@404: wenzelm@404: (* prepare introduction orule *) wenzelm@404: wenzelm@404: val _ = wenzelm@404: if Sign.subsort sign ([class], logicS) then () wenzelm@404: else err_not_logic class; wenzelm@404: wenzelm@404: fun axm_sort (name, ax) = wenzelm@404: (case term_tfrees ax of wenzelm@404: [] => [] wenzelm@404: | [(_, S)] => wenzelm@404: if Sign.subsort sign ([class], S) then S wenzelm@404: else err_bad_axsort name class wenzelm@404: | _ => err_bad_tfrees name); wenzelm@404: wenzelm@404: val axS = Sign.norm_sort sign (logicC :: flat (map axm_sort axioms)); wenzelm@404: wenzelm@404: val int_axm = close_form o map_term_tfrees (K (aT axS)); wenzelm@404: fun inclass c = mk_inclass (aT axS, c); wenzelm@404: wenzelm@404: val intro_axm = list_implies wenzelm@404: (map inclass super_classes @ map (int_axm o snd) axioms, inclass class); wenzelm@404: in wenzelm@404: add_axioms_i ((class ^ "I", intro_axm) :: abs_axioms) thy wenzelm@404: end; wenzelm@404: wenzelm@404: wenzelm@404: (* external interfaces *) wenzelm@404: wenzelm@404: val add_axclass = ext_axclass read_axm; wenzelm@404: val add_axclass_i = ext_axclass cert_axm; wenzelm@404: wenzelm@404: wenzelm@423: (* add signature classes *) wenzelm@404: wenzelm@423: fun ext_sigclass add_cnsts (class, super_classes) consts old_thy = wenzelm@423: old_thy wenzelm@423: |> add_axclass (class, super_classes) [] wenzelm@423: |> add_defsort [class] wenzelm@423: |> add_cnsts consts wenzelm@423: |> add_defsort (Type.defaultS (#tsig (Sign.rep_sg (sign_of old_thy)))); wenzelm@404: wenzelm@423: val add_sigclass = ext_sigclass add_consts; wenzelm@423: val add_sigclass_i = ext_sigclass add_consts_i; wenzelm@404: wenzelm@404: wenzelm@404: wenzelm@423: (** prove class relations and type arities **) wenzelm@423: wenzelm@423: (* class_axms *) wenzelm@404: wenzelm@404: fun class_axms thy = wenzelm@404: let wenzelm@404: val classes = Sign.classes (sign_of thy); wenzelm@404: val intros = map (fn c => c ^ "I") classes; wenzelm@404: in wenzelm@404: get_axioms thy intros @ wenzelm@404: map (class_triv thy) classes wenzelm@404: end; wenzelm@404: wenzelm@423: wenzelm@423: (* axclass_tac *) wenzelm@423: wenzelm@423: (*(1) repeatedly resolve goals of form "(| ty : c_class |)", wenzelm@423: try "cI" axioms first and use class_triv as last resort wenzelm@423: (2) rewrite goals using user supplied definitions wenzelm@423: (3) repeatedly resolve goals with user supplied non-definitions*) wenzelm@423: wenzelm@423: fun axclass_tac thy thms = wenzelm@423: TRY (REPEAT_FIRST (resolve_tac (class_axms thy))) THEN wenzelm@423: TRY (rewrite_goals_tac (filter is_defn thms)) THEN wenzelm@423: TRY (REPEAT_FIRST (resolve_tac (filter_out is_defn thms))); wenzelm@404: wenzelm@404: wenzelm@423: (* provers *) wenzelm@404: wenzelm@423: fun prove term_of str_of thy sig_prop thms usr_tac = wenzelm@404: let wenzelm@404: val sign = sign_of thy; wenzelm@423: val goal = cterm_of sign (term_of sig_prop); wenzelm@423: val tac = axclass_tac thy thms THEN (if_none usr_tac all_tac); wenzelm@423: in wenzelm@423: prove_goalw_cterm [] goal (K [tac]) wenzelm@423: end wenzelm@423: handle ERROR => error ("The error(s) above occurred while trying to prove " wenzelm@423: ^ quote (str_of sig_prop)); wenzelm@404: wenzelm@423: val prove_classrel = wenzelm@423: prove mk_classrel (fn (c1, c2) => c1 ^ " < " ^ c2); wenzelm@404: wenzelm@423: val prove_arity = wenzelm@423: prove mk_arity (fn (t, ss, c) => Type.str_of_arity (t, ss, [c])); wenzelm@404: wenzelm@404: wenzelm@423: (* make goals (for interactive use) *) wenzelm@423: wenzelm@423: fun mk_goal term_of thy sig_prop = wenzelm@423: goalw_cterm [] (cterm_of (sign_of thy) (term_of sig_prop)); wenzelm@423: wenzelm@423: val goal_subclass = mk_goal mk_classrel; wenzelm@423: val goal_arity = mk_goal mk_arity; wenzelm@423: wenzelm@423: wenzelm@423: wenzelm@423: (** add proved class relations and instances **) wenzelm@404: wenzelm@423: fun add_subclass (c1, c2) axms thms usr_tac thy = wenzelm@423: add_classrel_thms wenzelm@423: [prove_classrel thy (c1, c2) (get_axioms thy axms @ thms) usr_tac] thy; wenzelm@423: wenzelm@423: fun add_instance (t, ss, cs) axms thms usr_tac thy = wenzelm@423: let wenzelm@423: val usr_thms = get_axioms thy axms @ thms; wenzelm@423: fun prove c = wenzelm@423: prove_arity thy (t, ss, c) usr_thms usr_tac; wenzelm@423: in wenzelm@423: add_arity_thms (map prove cs) thy wenzelm@423: end; wenzelm@404: wenzelm@404: wenzelm@404: end; wenzelm@404: