Nominal/Ex/Lambda.thy
changeset 1833 2050b5723c04
parent 1831 16653e702d89
child 1835 636de31888a6
equal deleted inserted replaced
1832:4650d428b1b5 1833:2050b5723c04
   125 where
   125 where
   126     t_Var[intro]: "\<lbrakk>valid \<Gamma>; (x, T) \<in> set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Var x : T"
   126     t_Var[intro]: "\<lbrakk>valid \<Gamma>; (x, T) \<in> set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Var x : T"
   127   | t_App[intro]: "\<lbrakk>\<Gamma> \<turnstile> t1 : T1 \<rightarrow> T2 \<or> \<Gamma> \<turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> App t1 t2 : T2"
   127   | t_App[intro]: "\<lbrakk>\<Gamma> \<turnstile> t1 : T1 \<rightarrow> T2 \<or> \<Gamma> \<turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> App t1 t2 : T2"
   128   | t_Lam[intro]: "\<lbrakk>atom x \<sharp> \<Gamma>; (x, T1) # \<Gamma> \<turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Lam x t : T1 \<rightarrow> T2"
   128   | t_Lam[intro]: "\<lbrakk>atom x \<sharp> \<Gamma>; (x, T1) # \<Gamma> \<turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Lam x t : T1 \<rightarrow> T2"
   129 
   129 
   130 ML {*
   130 inductive
   131 val inductive_atomize = @{thms induct_atomize};
   131   typing' :: "(name\<times>ty) list\<Rightarrow>lam\<Rightarrow>ty\<Rightarrow>bool" ("_ \<Turnstile> _ : _" [60,60,60] 60) 
   132 
   132 where
   133 val atomize_conv = 
   133     t'_Var[intro]: "\<lbrakk>valid \<Gamma>; (x,T)\<in>set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<Turnstile> Var x : T"
   134   MetaSimplifier.rewrite_cterm (true, false, false) (K (K NONE))
   134   | t'_App[intro]: "\<lbrakk>\<Gamma> \<Turnstile> t1 : T1\<rightarrow>T2 \<and> \<Gamma> \<Turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> \<Turnstile> App t1 t2 : T2"
   135     (HOL_basic_ss addsimps inductive_atomize);
   135   | t'_Lam[intro]: "\<lbrakk>atom x\<sharp>\<Gamma>;(x,T1)#\<Gamma> \<Turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> \<Turnstile> Lam x t : T1\<rightarrow>T2"
   136 val atomize_intr = Conv.fconv_rule (Conv.prems_conv ~1 atomize_conv);
   136 
   137 fun atomize_induct ctxt = Conv.fconv_rule (Conv.prems_conv ~1
   137 inductive
   138   (Conv.params_conv ~1 (K (Conv.prems_conv ~1 atomize_conv)) ctxt));
   138   typing2' :: "(name\<times>ty) list\<Rightarrow>lam\<Rightarrow>ty\<Rightarrow>bool" ("_ 2\<Turnstile> _ : _" [60,60,60] 60) 
   139 *}
   139 where
   140 
   140     t2'_Var[intro]: "\<lbrakk>valid \<Gamma>; (x,T)\<in>set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> 2\<Turnstile> Var x : T"
   141 ML {*
   141   | t2'_App[intro]: "\<lbrakk>\<Gamma> 2\<Turnstile> t1 : T1\<rightarrow>T2 \<or> \<Gamma> 2\<Turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> 2\<Turnstile> App t1 t2 : T2"
   142 fun map_term f t = 
   142   | t2'_Lam[intro]: "\<lbrakk>atom x\<sharp>\<Gamma>;(x,T1)#\<Gamma> 2\<Turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> 2\<Turnstile> Lam x t : T1\<rightarrow>T2"
   143   (case f t of
   143 
   144      NONE => map_term' f t 
   144 inductive
   145    | x => x)
   145   typing'' :: "(name\<times>ty) list\<Rightarrow>lam\<Rightarrow>ty\<Rightarrow>bool" ("_ |\<Turnstile> _ : _" [60,60,60] 60)
   146 and map_term' f (t $ u) = 
   146 and  valid' :: "(name\<times>ty) list \<Rightarrow> bool"
   147     (case (map_term f t, map_term f u) of
   147 where
   148         (NONE, NONE) => NONE
   148     v1[intro]: "valid' []"
   149       | (SOME t'', NONE) => SOME (t'' $ u)
   149   | v2[intro]: "\<lbrakk>valid' \<Gamma>;atom x\<sharp>\<Gamma>\<rbrakk>\<Longrightarrow> valid' ((x,T)#\<Gamma>)"
   150       | (NONE, SOME u'') => SOME (t $ u'')
   150   | t'_Var[intro]: "\<lbrakk>valid' \<Gamma>; (x,T)\<in>set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> |\<Turnstile> Var x : T"
   151       | (SOME t'', SOME u'') => SOME (t'' $ u''))
   151   | t'_App[intro]: "\<lbrakk>\<Gamma> |\<Turnstile> t1 : T1\<rightarrow>T2; \<Gamma> |\<Turnstile> t2 : T1\<rbrakk> \<Longrightarrow> \<Gamma> |\<Turnstile> App t1 t2 : T2"
   152   | map_term' f (Abs (s, T, t)) = 
   152   | t'_Lam[intro]: "\<lbrakk>atom x\<sharp>\<Gamma>;(x,T1)#\<Gamma> |\<Turnstile> t : T2\<rbrakk> \<Longrightarrow> \<Gamma> |\<Turnstile> Lam x t : T1\<rightarrow>T2"
   153       (case map_term f t of
   153 
   154         NONE => NONE
   154 use "../../Nominal-General/nominal_eqvt.ML"
   155       | SOME t'' => SOME (Abs (s, T, t'')))
       
   156   | map_term' _ _  = NONE;
       
   157 
       
   158 fun map_thm_tac ctxt tac thm =
       
   159 let
       
   160   val monos = Inductive.get_monos ctxt
       
   161 in
       
   162   EVERY [cut_facts_tac [thm] 1, etac rev_mp 1,
       
   163     REPEAT_DETERM (FIRSTGOAL (resolve_tac monos)),
       
   164     REPEAT_DETERM (rtac impI 1 THEN (atac 1 ORELSE tac))]
       
   165 end
       
   166 
       
   167 (* 
       
   168  proves F[f t] from F[t] where F[t] is the given theorem  
       
   169   
       
   170   - F needs to be monotone
       
   171   - f returns either SOME for a term it fires 
       
   172     and NONE elsewhere 
       
   173 *)
       
   174 fun map_thm ctxt f tac thm =
       
   175 let
       
   176   val opt_goal_trm = map_term f (prop_of thm)
       
   177   fun prove goal = 
       
   178     Goal.prove ctxt [] [] goal (fn _ => map_thm_tac ctxt tac thm)
       
   179 in
       
   180   case opt_goal_trm of
       
   181     NONE => thm
       
   182   | SOME goal => prove goal
       
   183 end
       
   184 
       
   185 fun transform_prem ctxt names thm =
       
   186 let
       
   187   fun split_conj names (Const ("op &", _) $ p $ q) = 
       
   188       (case head_of p of
       
   189          Const (name, _) => if name mem names then SOME q else NONE
       
   190        | _ => NONE)
       
   191   | split_conj _ _ = NONE;
       
   192 in
       
   193   map_thm ctxt (split_conj names) (etac conjunct2 1) thm
       
   194 end
       
   195 *}
       
   196 
       
   197 ML {*
       
   198 open Nominal_Permeq
       
   199 open Nominal_ThmDecls
       
   200 *}
       
   201 
       
   202 ML {*
       
   203 fun mk_perm p trm =
       
   204 let
       
   205   val ty = fastype_of trm
       
   206 in
       
   207   Const (@{const_name "permute"}, @{typ "perm"} --> ty --> ty) $ p $ trm
       
   208 end
       
   209 
       
   210 fun mk_minus p = 
       
   211  Const (@{const_name "uminus"}, @{typ "perm => perm"}) $ p   
       
   212 *}
       
   213 
       
   214 ML {* 
       
   215 fun single_case_tac ctxt pred_names pi intro  = 
       
   216 let
       
   217   val thy = ProofContext.theory_of ctxt
       
   218   val cpi = Thm.cterm_of thy (mk_minus pi)
       
   219   val rule = Drule.instantiate' [] [SOME cpi] @{thm permute_boolE}
       
   220 in
       
   221   eqvt_strict_tac ctxt [] [] THEN' 
       
   222   SUBPROOF (fn {prems, context as ctxt, ...} =>
       
   223     let
       
   224       val prems' = map (transform_prem ctxt pred_names) prems
       
   225       val side_cond_tac = EVERY' 
       
   226         [ rtac rule, 
       
   227           eqvt_strict_tac ctxt @{thms permute_minus_cancel(2)} [],
       
   228           resolve_tac prems' ]
       
   229     in
       
   230       HEADGOAL (rtac intro THEN_ALL_NEW (resolve_tac prems' ORELSE' side_cond_tac)) 
       
   231     end) ctxt
       
   232 end
       
   233 *}
       
   234 
       
   235 ML {*
       
   236 fun prepare_pred params_no pi pred =
       
   237 let
       
   238   val (c, xs) = strip_comb pred;
       
   239   val (xs1, xs2) = chop params_no xs
       
   240 in
       
   241   HOLogic.mk_imp 
       
   242     (pred, list_comb (c, xs1 @ map (mk_perm pi) xs2))
       
   243 end
       
   244 *}
       
   245 
       
   246 ML {*
       
   247 fun transp ([] :: _) = []
       
   248   | transp xs = map hd xs :: transp (map tl xs);
       
   249 *}
       
   250 
       
   251 ML {* 
       
   252   Local_Theory.note;
       
   253   Local_Theory.notes;
       
   254   fold_map
       
   255 *}
       
   256 
       
   257 ML {*
       
   258 fun note_named_thm (name, thm) ctxt = 
       
   259 let
       
   260   val thm_name = Binding.qualified_name 
       
   261     (Long_Name.qualify (Long_Name.base_name name) "eqvt")
       
   262   val attr = Attrib.internal (K eqvt_add)
       
   263 in
       
   264   Local_Theory.note ((thm_name, [attr]), [thm]) ctxt
       
   265 end
       
   266 *}
       
   267 
       
   268 ML {*
       
   269 fun eqvt_rel_tac pred_name ctxt = 
       
   270 let
       
   271   val thy = ProofContext.theory_of ctxt
       
   272   val ({names, ...}, {raw_induct, intrs, ...}) =
       
   273     Inductive.the_inductive ctxt (Sign.intern_const thy pred_name)
       
   274   val raw_induct = atomize_induct ctxt raw_induct;
       
   275   val intros = map atomize_intr intrs;
       
   276   val params_no = length (Inductive.params_of raw_induct)
       
   277   val (([raw_concl], [raw_pi]), ctxt') = 
       
   278     ctxt |> Variable.import_terms false [concl_of raw_induct] 
       
   279          ||>> Variable.variant_fixes ["pi"]
       
   280   val pi = Free (raw_pi, @{typ perm})
       
   281   val preds = map (fst o HOLogic.dest_imp)
       
   282     (HOLogic.dest_conj (HOLogic.dest_Trueprop raw_concl));
       
   283   val goal = HOLogic.mk_Trueprop 
       
   284     (foldr1 HOLogic.mk_conj (map (prepare_pred params_no pi) preds))
       
   285   val thm = Goal.prove ctxt' [] [] goal (fn {context,...} => 
       
   286     HEADGOAL (EVERY' (rtac raw_induct :: map (single_case_tac context names pi) intros)))
       
   287     |> singleton (ProofContext.export ctxt' ctxt)
       
   288   val thms = map (fn th => zero_var_indexes (th RS mp)) (Datatype_Aux.split_conj_thm thm)
       
   289 in
       
   290    ctxt |> fold_map note_named_thm (names ~~ thms)
       
   291         |> snd
       
   292 end
       
   293 *}
       
   294 
       
   295 
       
   296 ML {*
       
   297 local structure P = OuterParse and K = OuterKeyword in
       
   298 
       
   299 val _ =
       
   300   OuterSyntax.local_theory "equivariance"
       
   301     "prove equivariance for inductive predicate involving nominal datatypes" K.thy_decl
       
   302     (P.xname >> eqvt_rel_tac);
       
   303 
       
   304 end;
       
   305 *}
       
   306 
   155 
   307 equivariance valid
   156 equivariance valid
   308 equivariance typing
   157 equivariance typing
   309 
   158 
   310 thm valid.eqvt
   159 thm valid.eqvt
   311 thm typing.eqvt
   160 thm typing.eqvt
   312 thm eqvts
   161 thm eqvts
   313 thm eqvts_raw
   162 thm eqvts_raw
       
   163 
       
   164 equivariance typing'
       
   165 equivariance typing2' 
       
   166 equivariance typing''
       
   167 
       
   168 ML {*
       
   169 fun mk_minus p = 
       
   170  Const (@{const_name "uminus"}, @{typ "perm => perm"}) $ p
       
   171 *}
       
   172 
       
   173 inductive
       
   174   tt :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a \<Rightarrow> bool)"  
       
   175   for r :: "('a \<Rightarrow> 'a \<Rightarrow> bool)"
       
   176 where
       
   177     "tt r a b"
       
   178   | "tt r a b ==> tt r a c"
       
   179 
       
   180 (*
       
   181 equivariance tt
       
   182 *)
   314 
   183 
   315 
   184 
   316 inductive
   185 inductive
   317  alpha_lam_raw'
   186  alpha_lam_raw'
   318 where
   187 where