| author | wenzelm | 
| Mon, 11 Jul 2022 13:40:10 +0200 | |
| changeset 75673 | eb7480f29adc | 
| parent 74632 | 8ab92e40dde6 | 
| child 77898 | b03c64699af0 | 
| permissions | -rw-r--r-- | 
| 63627 | 1 | (* Title: HOL/Analysis/measurable.ML | 
| 50387 | 2 | Author: Johannes Hölzl <hoelzl@in.tum.de> | 
| 3 | ||
| 4 | Measurability prover. | |
| 5 | *) | |
| 6 | ||
| 7 | signature MEASURABLE = | |
| 8 | sig | |
| 59048 | 9 | type preprocessor = thm -> Proof.context -> (thm list * Proof.context) | 
| 10 | ||
| 50387 | 11 | datatype level = Concrete | Generic | 
| 12 | ||
| 59047 | 13 | val dest_thm_attr : attribute context_parser | 
| 59048 | 14 | val cong_thm_attr : attribute context_parser | 
| 59047 | 15 | val measurable_thm_attr : bool * (bool * level) -> attribute | 
| 53043 
8cbfbeb566a4
more standard attribute_setup / method_setup -- export key ML operations instead of parsers;
 wenzelm parents: 
51717diff
changeset | 16 | |
| 59048 | 17 | val add_del_cong_thm : bool -> thm -> Context.generic -> Context.generic ; | 
| 18 | ||
| 19 | val get_all : Context.generic -> thm list | |
| 20 | val get_dest : Context.generic -> thm list | |
| 21 | val get_cong : Context.generic -> thm list | |
| 22 | ||
| 50387 | 23 | val measurable_tac : Proof.context -> thm list -> tactic | 
| 24 | ||
| 53043 
8cbfbeb566a4
more standard attribute_setup / method_setup -- export key ML operations instead of parsers;
 wenzelm parents: 
51717diff
changeset | 25 | val simproc : Proof.context -> cterm -> thm option | 
| 50387 | 26 | |
| 59048 | 27 | val add_preprocessor : string -> preprocessor -> Context.generic -> Context.generic | 
| 28 | val del_preprocessor : string -> Context.generic -> Context.generic | |
| 29 | val add_local_cong : thm -> Proof.context -> Proof.context | |
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 30 | |
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 31 | val prepare_facts : Proof.context -> thm list -> (thm list * Proof.context) | 
| 50387 | 32 | end ; | 
| 33 | ||
| 34 | structure Measurable : MEASURABLE = | |
| 35 | struct | |
| 36 | ||
| 59048 | 37 | type preprocessor = thm -> Proof.context -> (thm list * Proof.context) | 
| 38 | ||
| 50387 | 39 | datatype level = Concrete | Generic; | 
| 40 | ||
| 59047 | 41 | fun eq_measurable_thms ((th1, d1), (th2, d2)) = | 
| 42 | d1 = d2 andalso Thm.eq_thm_prop (th1, th2) ; | |
| 43 | ||
| 59048 | 44 | fun merge_dups (xs:(string * preprocessor) list) ys = | 
| 45 | xs @ (filter (fn (name, _) => is_none (find_first (fn (name', _) => name' = name) xs)) ys) | |
| 46 | ||
| 50387 | 47 | structure Data = Generic_Data | 
| 48 | ( | |
| 49 |   type T = {
 | |
| 59047 | 50 | measurable_thms : (thm * (bool * level)) Item_Net.T, | 
| 50387 | 51 | dest_thms : thm Item_Net.T, | 
| 59048 | 52 | cong_thms : thm Item_Net.T, | 
| 53 | preprocessors : (string * preprocessor) list } | |
| 59992 | 54 |   val empty: T = {
 | 
| 59047 | 55 | measurable_thms = Item_Net.init eq_measurable_thms (single o Thm.prop_of o fst), | 
| 74152 | 56 | dest_thms = Thm.item_net, | 
| 57 | cong_thms = Thm.item_net, | |
| 59048 | 58 | preprocessors = [] }; | 
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 59 |   fun merge ({measurable_thms = t1, dest_thms = dt1, cong_thms = ct1, preprocessors = i1 },
 | 
| 59992 | 60 |       {measurable_thms = t2, dest_thms = dt2, cong_thms = ct2, preprocessors = i2 }) : T = {
 | 
| 59047 | 61 | measurable_thms = Item_Net.merge (t1, t2), | 
| 50387 | 62 | dest_thms = Item_Net.merge (dt1, dt2), | 
| 59048 | 63 | cong_thms = Item_Net.merge (ct1, ct2), | 
| 64 | preprocessors = merge_dups i1 i2 | |
| 65 | }; | |
| 50387 | 66 | ); | 
| 67 | ||
| 68 | val debug = | |
| 69597 | 69 | Attrib.setup_config_bool \<^binding>\<open>measurable_debug\<close> (K false) | 
| 50387 | 70 | |
| 71 | val split = | |
| 69597 | 72 | Attrib.setup_config_bool \<^binding>\<open>measurable_split\<close> (K true) | 
| 50387 | 73 | |
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 74 | fun map_data f1 f2 f3 f4 | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 75 |   {measurable_thms = t1,    dest_thms = t2,    cong_thms = t3,    preprocessors = t4 } =
 | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 76 |   {measurable_thms = f1 t1, dest_thms = f2 t2, cong_thms = f3 t3, preprocessors = f4 t4}
 | 
| 50387 | 77 | |
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 78 | fun map_measurable_thms f = map_data f I I I | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 79 | fun map_dest_thms f = map_data I f I I | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 80 | fun map_cong_thms f = map_data I I f I | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 81 | fun map_preprocessors f = map_data I I I f | 
| 50387 | 82 | |
| 59992 | 83 | fun generic_add_del map : attribute context_parser = | 
| 59047 | 84 | Scan.lift | 
| 85 | (Args.add >> K Item_Net.update || Args.del >> K Item_Net.remove || Scan.succeed Item_Net.update) >> | |
| 86 | (fn f => Thm.declaration_attribute (Data.map o map o f)) | |
| 87 | ||
| 88 | val dest_thm_attr = generic_add_del map_dest_thms | |
| 50387 | 89 | |
| 59048 | 90 | val cong_thm_attr = generic_add_del map_cong_thms | 
| 91 | ||
| 59047 | 92 | fun del_thm th net = | 
| 93 | let | |
| 94 | val thms = net |> Item_Net.content |> filter (fn (th', _) => Thm.eq_thm (th, th')) | |
| 95 | in fold Item_Net.remove thms net end ; | |
| 96 | ||
| 97 | fun measurable_thm_attr (do_add, d) = Thm.declaration_attribute | |
| 98 | (Data.map o map_measurable_thms o (if do_add then Item_Net.update o rpair d else del_thm)) | |
| 50387 | 99 | |
| 100 | val get_dest = Item_Net.content o #dest_thms o Data.get; | |
| 101 | ||
| 59048 | 102 | val get_cong = Item_Net.content o #cong_thms o Data.get; | 
| 103 | val add_cong = Data.map o map_cong_thms o Item_Net.update; | |
| 104 | val del_cong = Data.map o map_cong_thms o Item_Net.remove; | |
| 105 | fun add_del_cong_thm true = add_cong | |
| 106 | | add_del_cong_thm false = del_cong | |
| 107 | ||
| 108 | fun add_preprocessor name f = Data.map (map_preprocessors (fn xs => xs @ [(name, f)])) | |
| 109 | fun del_preprocessor name = Data.map (map_preprocessors (filter (fn (n, _) => n <> name))) | |
| 110 | val add_local_cong = Context.proof_map o add_cong | |
| 111 | ||
| 112 | val get_preprocessors = Context.Proof #> Data.get #> #preprocessors ; | |
| 113 | ||
| 50387 | 114 | fun is_too_generic thm = | 
| 115 | let | |
| 59582 | 116 | val concl = Thm.concl_of thm | 
| 50387 | 117 | val concl' = HOLogic.dest_Trueprop concl handle TERM _ => concl | 
| 118 | in is_Var (head_of concl') end | |
| 119 | ||
| 59048 | 120 | val get_thms = Data.get #> #measurable_thms #> Item_Net.content ; | 
| 58965 | 121 | |
| 59048 | 122 | val get_all = get_thms #> map fst ; | 
| 50387 | 123 | |
| 59048 | 124 | fun debug_tac ctxt msg f = | 
| 125 | if Config.get ctxt debug then print_tac ctxt (msg ()) THEN f else f | |
| 50387 | 126 | |
| 127 | fun nth_hol_goal thm i = | |
| 59582 | 128 | HOLogic.dest_Trueprop (Logic.strip_imp_concl (strip_all_body (nth (Thm.prems_of thm) (i - 1)))) | 
| 50387 | 129 | |
| 130 | fun dest_measurable_fun t = | |
| 131 | (case t of | |
| 74632 | 132 | \<^Const_>\<open>Set.member _ for f \<^Const_>\<open>measurable _ _ for _ _\<close>\<close> => f | 
| 50387 | 133 |   | _ => raise (TERM ("not a measurability predicate", [t])))
 | 
| 134 | ||
| 59582 | 135 | fun not_measurable_prop n thm = | 
| 136 | if length (Thm.prems_of thm) < n then false | |
| 137 | else | |
| 138 | (case nth_hol_goal thm n of | |
| 74632 | 139 | \<^Const_>\<open>Set.member _ for _ \<^Const_>\<open>sets _ for _\<close>\<close> => false | 
| 140 | | \<^Const_>\<open>Set.member _ for _ \<^Const_>\<open>measurable _ _ for _ _\<close>\<close> => false | |
| 59582 | 141 | | _ => true) | 
| 142 | handle TERM _ => true; | |
| 50387 | 143 | |
| 144 | fun indep (Bound i) t b = i < b orelse t <= i | |
| 145 | | indep (f $ t) top bot = indep f top bot andalso indep t top bot | |
| 146 | | indep (Abs (_,_,t)) top bot = indep t (top + 1) (bot + 1) | |
| 147 | | indep _ _ _ = true; | |
| 148 | ||
| 59837 | 149 | fun cnt_prefixes ctxt (Abs (n, T, t)) = | 
| 150 | let | |
| 69597 | 151 | fun is_countable ty = Sign.of_sort (Proof_Context.theory_of ctxt) (ty, \<^sort>\<open>countable\<close>) | 
| 50387 | 152 | fun cnt_walk (Abs (ns, T, t)) Ts = | 
| 153 | map (fn (t', t'') => (Abs (ns, T, t'), t'')) (cnt_walk t (T::Ts)) | |
| 154 | | cnt_walk (f $ g) Ts = let | |
| 155 | val n = length Ts - 1 | |
| 156 | in | |
| 157 | map (fn (f', t) => (f' $ g, t)) (cnt_walk f Ts) @ | |
| 158 | map (fn (g', t) => (f $ g', t)) (cnt_walk g Ts) @ | |
| 159 | (if is_countable (type_of1 (Ts, g)) andalso loose_bvar1 (g, n) | |
| 160 | andalso indep g n 0 andalso g <> Bound n | |
| 161 | then [(f $ Bound (n + 1), incr_boundvars (~ n) g)] | |
| 162 | else []) | |
| 163 | end | |
| 164 | | cnt_walk _ _ = [] | |
| 165 | in map (fn (t1, t2) => let | |
| 166 | val T1 = type_of1 ([T], t2) | |
| 167 | val T2 = type_of1 ([T], t) | |
| 168 | in ([SOME (Abs (n, T1, Abs (n, T, t1))), NONE, NONE, SOME (Abs (n, T, t2))], | |
| 169 | [SOME T1, SOME T, SOME T2]) | |
| 170 | end) (cnt_walk t [T]) | |
| 171 | end | |
| 172 | | cnt_prefixes _ _ = [] | |
| 173 | ||
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 174 | fun apply_dests thm dests = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 175 | let | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 176 | fun apply thm th' = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 177 | let | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 178 | val th'' = thm RS th' | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 179 | in [th''] @ loop th'' end | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 180 | handle (THM _) => [] | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 181 | and loop thm = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 182 | flat (map (apply thm) dests) | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 183 | in | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 184 |     [thm] @ ([thm RS @{thm measurable_compose_rev}] handle (THM _) => []) @ loop thm
 | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 185 | end | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 186 | |
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 187 | fun prepare_facts ctxt facts = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 188 | let | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 189 | val dests = get_dest (Context.Proof ctxt) | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 190 | fun prep_dest thm = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 191 | (if is_too_generic thm then [] else apply_dests thm dests) ; | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 192 |     val preprocessors = (("std", prep_dest #> pair) :: get_preprocessors ctxt) ;
 | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 193 | fun preprocess_thm (thm, raw) = | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 194 | if raw then pair [thm] else fold_map (fn (_, proc) => proc thm) preprocessors #>> flat | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 195 | |
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 196 | fun sel lv (th, (raw, lv')) = if lv = lv' then SOME (th, raw) else NONE ; | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 197 | fun get lv = ctxt |> Context.Proof |> get_thms |> rev |> map_filter (sel lv) ; | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 198 | val pre_thms = map (Simplifier.norm_hhf ctxt #> rpair false) facts @ get Concrete @ get Generic | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 199 | |
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 200 | val (thms, ctxt) = fold_map preprocess_thm pre_thms ctxt |>> flat | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 201 | in (thms, ctxt) end | 
| 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 202 | |
| 59047 | 203 | fun measurable_tac ctxt facts = | 
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
50387diff
changeset | 204 | let | 
| 59048 | 205 | fun debug_fact msg thm () = | 
| 61877 
276ad4354069
renamed Pretty.str_of to Pretty.unformatted_string_of to emphasize its meaning;
 wenzelm parents: 
61424diff
changeset | 206 | msg ^ " " ^ Pretty.unformatted_string_of (Syntax.pretty_term ctxt (Thm.prop_of thm)) | 
| 59048 | 207 | |
| 208 | fun IF' c t i = COND (c i) (t i) no_tac | |
| 209 | ||
| 210 | fun r_tac msg = | |
| 211 | if Config.get ctxt debug | |
| 212 | then FIRST' o | |
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
59353diff
changeset | 213 | map (fn thm => resolve_tac ctxt [thm] | 
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 214 | THEN' K (debug_tac ctxt (debug_fact (msg ^ " resolved using") thm) all_tac)) | 
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
59353diff
changeset | 215 | else resolve_tac ctxt | 
| 59048 | 216 | |
| 59353 
f0707dc3d9aa
measurability prover: removed app splitting, replaced by more powerful destruction rules
 hoelzl parents: 
59048diff
changeset | 217 | val (thms, ctxt) = prepare_facts ctxt facts | 
| 50387 | 218 | |
| 74632 | 219 | fun is_sets_eq \<^Const_>\<open>HOL.eq _ for | 
| 220 | \<^Const_>\<open>sets _ for _\<close> \<^Const_>\<open>sets _ for _\<close>\<close> = true | |
| 221 | | is_sets_eq \<^Const_>\<open>HOL.eq _ for | |
| 222 | \<^Const_>\<open>measurable _ _ for _ _\<close> \<^Const_>\<open>measurable _ _ for _ _\<close>\<close> = true | |
| 59048 | 223 | | is_sets_eq _ = false | 
| 224 | ||
| 225 | val cong_thms = get_cong (Context.Proof ctxt) @ | |
| 59582 | 226 | filter (fn thm => Thm.concl_of thm |> HOLogic.dest_Trueprop |> is_sets_eq handle TERM _ => false) facts | 
| 59048 | 227 | |
| 228 | fun sets_cong_tac i = | |
| 229 |       Subgoal.FOCUS (fn {context = ctxt', prems = prems, ...} => (
 | |
| 230 | let | |
| 231 | val ctxt'' = Simplifier.add_prems prems ctxt' | |
| 232 | in | |
| 74632 | 233 |           r_tac "cong intro" [@{lemma "A = B \<Longrightarrow> x \<in> B \<Longrightarrow> x \<in> A" by simp}]
 | 
| 59048 | 234 | THEN' SOLVED' (fn i => REPEAT_DETERM ( | 
| 235 |               ((r_tac "cong solve" (cong_thms @ [@{thm refl}])
 | |
| 59582 | 236 | ORELSE' IF' (fn i => fn thm => Thm.nprems_of thm > i) | 
| 59048 | 237 | (SOLVED' (asm_full_simp_tac ctxt''))) i))) | 
| 238 | end) 1) ctxt i | |
| 239 | THEN flexflex_tac ctxt | |
| 240 | ||
| 241 | val simp_solver_tac = | |
| 242 | IF' not_measurable_prop (debug_tac ctxt (K "simp ") o SOLVED' (asm_full_simp_tac ctxt)) | |
| 243 | ||
| 244 | val split_countable_tac = | |
| 245 |       Subgoal.FOCUS (fn {context = ctxt, ...} => SUBGOAL (fn (t, i) =>
 | |
| 246 | let | |
| 247 | val f = dest_measurable_fun (HOLogic.dest_Trueprop t) | |
| 248 | fun inst (ts, Ts) = | |
| 60807 | 249 | Thm.instantiate' | 
| 250 | (map (Option.map (Thm.ctyp_of ctxt)) Ts) | |
| 251 | (map (Option.map (Thm.cterm_of ctxt)) ts) | |
| 59498 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 wenzelm parents: 
59353diff
changeset | 252 |               @{thm measurable_compose_countable}
 | 
| 61424 
c3658c18b7bc
prod_case as canonical name for product type eliminator
 haftmann parents: 
60807diff
changeset | 253 | in r_tac "case_prod countable" (cnt_prefixes ctxt f |> map inst) i end | 
| 59048 | 254 | handle TERM _ => no_tac) 1) | 
| 50387 | 255 | |
| 256 | val splitter = if Config.get ctxt split then split_countable_tac ctxt else K no_tac | |
| 257 | ||
| 59048 | 258 | val single_step_tac = | 
| 259 | simp_solver_tac | |
| 260 | ORELSE' r_tac "step" thms | |
| 261 | ORELSE' splitter | |
| 262 | ORELSE' (CHANGED o sets_cong_tac) | |
| 263 | ORELSE' (K (debug_tac ctxt (K "backtrack") no_tac)) | |
| 50387 | 264 | |
| 59048 | 265 | in debug_tac ctxt (K "start") (REPEAT (single_step_tac 1)) end; | 
| 50387 | 266 | |
| 51717 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
50387diff
changeset | 267 | fun simproc ctxt redex = | 
| 
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
 wenzelm parents: 
50387diff
changeset | 268 | let | 
| 59582 | 269 | val t = HOLogic.mk_Trueprop (Thm.term_of redex); | 
| 50387 | 270 |     fun tac {context = ctxt, prems = _ } =
 | 
| 59047 | 271 | SOLVE (measurable_tac ctxt (Simplifier.prems_of ctxt)); | 
| 73551 | 272 |   in \<^try>\<open>Goal.prove ctxt [] [] t tac RS @{thm Eq_TrueI}\<close> end;
 | 
| 50387 | 273 | |
| 274 | end | |
| 275 |