(*generate show functions for the given datatype*) val generate_showsp : string -> local_theory -> local_theory
val register_foreign_partial_and_full_showsp : string -> (*type name*)
int -> (*default precedence for type parameters*)
term -> (*partial show function*)
term -> (*show function*)
thm option -> (*definition of show function via partial show function*)
term -> (*map function*)
thm option -> (*compositionality theorem of map function*) boollist -> (*indicate which positions of type parameters are used*)
thm -> (*show law intro rule*)
local_theory -> local_theory
(*for type constants (i.e., nullary type constructors) partial and full show functions
coincide and no other information is necessary.*) val register_foreign_showsp : typ -> term -> thm -> local_theory -> local_theory
(*automatically derive a "show" class instance for the given datatype*) val show_instance : string -> theory -> theory
val mk_prec = HOLogic.mk_number @{typ nat} val prec0 = mk_prec 0 val prec1 = mk_prec 1 val showS = @{sort "show"} val showsT = @{typ "shows"} fun showspT T = @{typ nat} --> T --> showsT val showsify_typ = map_atyps (K showsT) val showsify = map_types showsify_typ fun show_law_const T = \<^Const>\<open>show_law T\<close> fun shows_prec_const T = \<^Const>\<open>shows_prec T\<close> fun shows_list_const T = \<^Const>\<open>shows_list T\<close> fun showsp_list_const T = \<^Const>\<open>showsp_list T\<close> val dest_showspT = binder_types #> tl #> hd
structure Data = Generic_Data
( type T = info Symtab.table val empty = Symtab.empty val merge = Symtab.merge (fn (info1, info2) => #pshowsp info1 = #pshowsp info2)
)
fun add_info tyco info = Data.map (Symtab.update_new (tyco, info)) val get_info = Context.Proof #> Data.get #> Symtab.lookup
fun the_info ctxt tyco =
(case get_info ctxt tyco of
SOME info => info
| NONE => error ("no show function available for type " ^ quote tyco))
val register_foreign_partial_and_full_showsp = declare_info
fun register_foreign_showsp T show = letval tyco = (case T ofType (tyco, []) => tyco | _ => error "expected type constant") in register_foreign_partial_and_full_showsp tyco 0 show show NONE (HOLogic.id_const T) NONE [] end
fun shows_string c =
\<^Const>\<open>shows_string for \<open>HOLogic.mk_string (Long_Name.base_name c)\<close>\<close>
fun mk_shows_parens _ [t] = t
| mk_shows_parens p ts = Library.foldl1 HOLogic.mk_comp
(\<^Const>\<open>shows_pl for p\<close> :: separate \<^Const>\<open>shows_space\<close> ts @ [\<^Const>\<open>shows_pr for p\<close>])
fun simp_only_tac ctxt ths =
CHANGED o full_simp_tac (clear_simpset (put_simpset HOL_basic_ss ctxt) addsimps ths)
fun generate_showsp tyco lthy = let val (tycos, Ts) = mutual_recursive_types tyco lthy val _ = map (fn tyco => "generating show function for type " ^ quote tyco) tycos
|> cat_lines |> writeln
val maps = Bnf_Access.map_terms lthy tycos val map_simps = Bnf_Access.map_simps lthy tycos val map_comps = Bnf_Access.map_comps lthy tycos
val (tfrees, used_tfrees) = type_parameters (hd Ts) lthy val used_positions = map (member (op =) used_tfrees o TFree) tfrees val ss = map (subT "show") used_tfrees val show_Ts = map showspT used_tfrees val arg_shows = map Free (ss ~~ show_Ts) val dep_tycos = fold (add_used_tycos lthy) tycos []
fun mk_pshowsp (tyco, T) =
("pshowsp_" ^ Long_Name.base_name tyco, showspT T |> showsify_typ) fun default_show T = absdummy T (mk_id @{typ string})
fun constr_terms lthy = Bnf_Access.constr_terms lthy #> map (apsnd (fst o strip_type) o dest_Const)
(* primrec definitions of partial show functions *)
fun generate_pshow_eqs lthy (tyco, T) = let val constrs = constr_terms lthy tyco
|> map (fn (c, Ts) => letval Ts' = map showsify_typ Ts in (Const (c, Ts' ---> T) |> showsify, Ts') end)
fun shows_arg (x, T) = let val m = Generator_Aux.create_map default_show
(fn (tyco, T) => fn p => Free (mk_pshowsp (tyco, T)) $ p) prec1
(equal @{typ "shows"})
(#used_positions oo the_info) (#map oo the_info)
(curry (op $) o #pshowsp oo the_info)
tycos (mk_prec o #prec oo the_info) T lthy val pshow = Generator_Aux.create_partial prec1 (equal @{typ "shows"})
(#used_positions oo the_info) (#map oo the_info)
(curry (op $) o #pshowsp oo the_info)
tycos (mk_prec o #prec oo the_info) T lthy in pshow $ (m $ Free (x, T)) |> infer_type lthy end
fun generate_eq lthy (c, arg_Ts) = let val (p, xs) = Name.variant "p" (Variable.names_of lthy) |>> Free o rpair @{typ nat}
||> (fn ctxt => Name.invent_names ctxt "x" arg_Ts) val lhs = Free (mk_pshowsp (tyco, T)) $ p $ list_comb (c, map Free xs) val rhs = shows_string (dest_Const c |> fst) :: map shows_arg xs
|> mk_shows_parens p in HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs, rhs)) end inmap (generate_eq lthy) constrs end
val induct_thms = Bnf_Access.induct_thms lthy tycos val set_simps = Bnf_Access.set_simps lthy tycos val sets = Bnf_Access.set_terms lthy tycos
fun generate_show_law_thms (tyco, x) = let val sets = AList.lookup (op =) (tycos ~~ sets) tyco |> the val used_sets = map (the o AList.lookup (op =) (map TFree tfrees ~~ sets)) used_tfrees fun mk_prem ((show, set), T) = let (*val y = singleton (Name.variant_list [fst x]) "y" |> Free o rpair T*) val y = Free (subT "x" T, T) val lhs = HOLogic.mk_mem (y, set $ Free x) |> HOLogic.mk_Trueprop val rhs = show_law_const T $ show $ y |> HOLogic.mk_Trueprop in Logic.all y (Logic.mk_implies (lhs, rhs)) end val prems = map mk_prem (arg_shows ~~ used_sets ~~ used_tfrees) val (show_const, T) = AList.lookup (op =) (tycos ~~ (shows ~~ Ts)) tyco |> the val concl = show_law_const T $ list_comb (show_const, arg_shows) $ Free x
|> HOLogic.mk_Trueprop in Logic.list_implies (prems, concl) |> infer_type lthy end
val xs = Name.invent_names (Variable.names_of lthy) "x" Ts val show_law_prethms = map generate_show_law_thms (tycos ~~ xs)
val rec_info = (the_info lthy, #used_positions, tycos) val split_IHs = split_IHs rec_info
val recursor_tac = std_recursor_tac rec_info used_tfrees #show_law_intro
fun show_law_tac ctxt xs = let val constr_Ts = tycos
|> map (#ctrXs_Tss o #fp_ctr_sugar o the o BNF_FP_Def_Sugar.fp_sugar_of ctxt)
val ind_case_to_idxs = let fun number n (i, j) ((_ :: xs) :: ys) = (n, (i, j)) :: number (n + 1) (i, j + 1) (xs :: ys)
| number n (i, _) ([] :: ys) = number n (i + 1, 0) ys
| number _ _ [] = [] in AList.lookup (op =) (number 0 (0, 0) constr_Ts) #> the end
fun instantiate_IHs IHs assms = map (fn IH =>
OF_option IH (replicate (Thm.nprems_of IH - length assms) NONE @ map SOME assms)) IHs
fun induct_tac ctxt f =
(DETERM o Induction.induction_tac ctxt false
(map (fn x => [SOME (NONE, (x, false))]) xs) [] [] (SOME induct_thms) [])
THEN_ALL_NEW (fn st =>
Subgoal.SUBPROOF (fn {context = ctxt, prems, params, ...} =>
f ctxt (st - 1) prems params) ctxt st)
(*do not use full "show_law_simps" here, since otherwise too many subgoalsmightbesolved(sothatthenumberofsubgoalsdoesnolonger
match the number of IHs)*) val show_law_simps_less = @{thms
shows_string_append shows_pl_append shows_pr_append shows_space_append}
fun o_append_intro_tac ctxt f = HEADGOAL (
K (Method.try_intros_tac ctxt @{thms o_append} [])
THEN_ALL_NEW K (unfold_tac ctxt show_law_simps_less)
THEN_ALL_NEW (fn i => Subgoal.SUBPROOF (fn {context = ctxt', ...} =>
f (i - 1) ctxt') ctxt i))
fun solve_tac ctxt case_num prems params = let val (i, _) = ind_case_to_idxs case_num (*(constructor number, argument number)*) val k = length prems - length used_tfrees val (IHs, assms) = chop k prems in
resolve_tac ctxt @{thms show_lawI} 1 THEN Subgoal.FOCUS (fn {context = ctxt, ...} => let val assms = map (Local_Defs.unfold ctxt (nth set_simps i)) assms val Ts = map (fastype_of o Thm.term_of o snd) params val IHs = instantiate_IHs IHs assms |> split_IHs Ts in
unfold_tac ctxt (nth show_simps i) THEN o_append_intro_tac ctxt (fn i => fn ctxt' =>
resolve_tac ctxt' @{thms show_lawD} 1 THEN recursor_tac assms (nth Ts i) (nth IHs i) ctxt') end) ctxt 1 end in induct_tac ctxt solve_tac end
in
lthy
|> fold (fn ((((((tyco, pshow), show), show_def), m), m_comp), law_thm) =>
declare_info tyco 1 pshow show (SOME show_def) m (SOME m_comp) used_positions law_thm)
(tycos ~~ pshows ~~ shows ~~ show_defs ~~ maps ~~ map_comps ~~ show_law_thms) end
fun ensure_info tyco lthy =
(case get_info lthy tyco of
SOME _ => lthy
| NONE => generate_showsp tyco lthy)
(* proving show instances *)
fun dest_showsp showsp =
dest_Const showsp
||> (
binder_types #> chop_prefix (fn T => T <> @{typ nat})
#>> map (freeify_tvars o dest_showspT)
##> map (dest_TFree o freeify_tvars) o snd o dest_Type o hd o tl)
fun show_instance tyco thy = let val _ = Sorts.has_instance (Sign.classes_of thy) tyco showS
andalso error ("type " ^ quote tyco ^ " is already an instance of class \"show\"") val _ = writeln ("deriving \"show\" instance for type " ^ quote tyco) val thy = Named_Target.theory_map (ensure_info tyco) thy val lthy = Named_Target.theory_init thy val {showsp, ...} = the_info lthy tyco val (showspN, (used_tfrees, tfrees)) = dest_showsp showsp val tfrees' = tfrees
|> map (fn (x, S) => if member (op =) used_tfrees (TFree (x, S)) then (x, showS) else (x, S)) val used_tfrees' = map (dest_TFree #> fst #> rpair showS #> TFree) used_tfrees val T = Type (tyco, map TFree tfrees') val arg_Ts = map showspT used_tfrees' val showsp' = Const (showspN, arg_Ts ---> showspT T) val shows_prec_def = Logic.mk_equals
(shows_prec_const T, list_comb (showsp', map shows_prec_const used_tfrees')) val shows_list_def = Logic.mk_equals
(shows_list_const T, showsp_list_const T $ shows_prec_const T $ prec0) val name = Long_Name.base_name tyco val ((shows_prec_thm, shows_list_thm), lthy) =
Class.instantiation ([tyco], tfrees', showS) thy
|> Generator_Aux.define_overloaded_generic
((Binding.name ("shows_prec_" ^ name ^ "_def"), [Code.singleton_default_equation_attrib]), shows_prec_def)
||>> Generator_Aux.define_overloaded_generic
((Binding.name ("shows_list_" ^ name ^ "_def"), [Code.singleton_default_equation_attrib]), shows_list_def) in
Class.prove_instantiation_exit (fn ctxt => let val show_law_intros = Named_Theorems.get ctxt @{named_theorems "show_law_intros"} val show_law_simps = Named_Theorems.get ctxt @{named_theorems "show_law_simps"} val show_append_tac = resolve_tac ctxt @{thms show_lawD} THEN' REPEAT_ALL_NEW (resolve_tac ctxt show_law_intros)
THEN_ALL_NEW (
resolve_tac ctxt @{thms show_lawI} THEN' simp_only_tac ctxt show_law_simps) in
Class.intro_classes_tac ctxt [] THEN unfold_tac ctxt [shows_prec_thm, shows_list_thm] THEN REPEAT1 (HEADGOAL show_append_tac) end) lthy end
val _ =
Theory.setup
(Derive_Manager.register_derive "show""generate show instance" (K o show_instance))
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.