# HG changeset patch # User berghofe # Date 1224616922 -7200 # Node ID 2822c56dd1cf8239afec3e75cce647d22e168aae # Parent 2f98571264983ae2098ce08647f8d9b67605d38f Example for using the generalized version of nominal_inductive. diff -r 2f9857126498 -r 2822c56dd1cf src/HOL/Nominal/Examples/W.thy --- a/src/HOL/Nominal/Examples/W.thy Tue Oct 21 21:20:46 2008 +0200 +++ b/src/HOL/Nominal/Examples/W.thy Tue Oct 21 21:22:02 2008 +0200 @@ -1,9 +1,317 @@ (* "$Id$" *) theory W -imports "Nominal" +imports Nominal begin -text {* stub until a cleaned-up version will appear here *} +text {* Example for strong induction rules avoiding sets of atoms. *} + +atom_decl tvar var + +abbreviation + "difference_list" :: "'a list \ 'a list \ 'a list" ("_ - _" [60,60] 60) +where + "xs - ys \ [x \ xs. x\set ys]" + +lemma difference_eqvt_tvar[eqvt]: + fixes pi::"tvar prm" + and Xs Ys::"tvar list" + shows "pi\(Xs - Ys) = (pi\Xs) - (pi\Ys)" +by (induct Xs) (simp_all add: eqvts) + +lemma difference_fresh: + fixes X::"tvar" + and Xs Ys::"tvar list" + assumes a: "X\set Ys" + shows "X\(Xs - Ys)" +using a +by (induct Xs) (auto simp add: fresh_list_nil fresh_list_cons fresh_atm) + +nominal_datatype ty = + TVar "tvar" + | Fun "ty" "ty" ("_\_" [100,100] 100) + +nominal_datatype tyS = + Ty "ty" + | ALL "\tvar\tyS" ("\[_]._" [100,100] 100) + +nominal_datatype trm = + Var "var" + | App "trm" "trm" + | Lam "\var\trm" ("Lam [_]._" [100,100] 100) + | Let "\var\trm" "trm" + +abbreviation + LetBe :: "var \ trm \ trm \ trm" ("Let _ be _ in _" [100,100,100] 100) +where + "Let x be t1 in t2 \ trm.Let x t2 t1" + +types + Ctxt = "(var\tyS) list" + +text {* free type variables *} +consts + ftv :: "'a \ tvar list" + +primrec (ftv_of_prod) + "ftv (x,y) = (ftv x)@(ftv y)" + +defs (overloaded) + ftv_of_tvar[simp]: "ftv X \ [(X::tvar)]" + ftv_of_var[simp]: "ftv (x::var) \ []" + +primrec (ftv_of_list) + "ftv [] = []" + "ftv (x#xs) = (ftv x)@(ftv xs)" + +(* free type-variables of types *) +nominal_primrec (ftv_ty) + "ftv (TVar X) = [X]" + "ftv (T\<^isub>1\T\<^isub>2) = (ftv T\<^isub>1)@(ftv T\<^isub>2)" +by (rule TrueI)+ + +lemma ftv_ty_eqvt[eqvt]: + fixes pi::"tvar prm" + and T::"ty" + shows "pi\(ftv T) = ftv (pi\T)" +by (nominal_induct T rule: ty.strong_induct) + (perm_simp add: append_eqvt)+ + +nominal_primrec (ftv_tyS) + "ftv (Ty T) = ftv T" + "ftv (\[X].S) = (ftv S) - [X]" +apply(finite_guess add: ftv_ty_eqvt fs_tvar1)+ +apply(rule TrueI)+ +apply(rule difference_fresh) +apply(simp) +apply(fresh_guess add: ftv_ty_eqvt fs_tvar1)+ +done + +lemma ftv_tyS_eqvt[eqvt]: + fixes pi::"tvar prm" + and S::"tyS" + shows "pi\(ftv S) = ftv (pi\S)" +apply(nominal_induct S rule: tyS.strong_induct) +apply(simp add: eqvts) +apply(simp only: ftv_tyS.simps) +apply(simp only: eqvts) +apply(simp add: eqvts) +done + +lemma ftv_Ctxt_eqvt[eqvt]: + fixes pi::"tvar prm" + and \::"Ctxt" + shows "pi\(ftv \) = ftv (pi\\)" +by (induct \) (auto simp add: eqvts) + +text {* Valid *} +inductive + valid :: "Ctxt \ bool" +where + V_Nil[intro]: "valid []" +| V_Cons[intro]: "\valid \;x\\\\ valid ((x,S)#\)" + +equivariance valid + +text {* General *} +consts + gen :: "ty \ tvar list \ tyS" + +primrec + "gen T [] = Ty T" + "gen T (X#Xs) = \[X].(gen T Xs)" + +lemma gen_eqvt[eqvt]: + fixes pi::"tvar prm" + shows "pi\(gen T Xs) = gen (pi\T) (pi\Xs)" +by (induct Xs) (simp_all add: eqvts) + +abbreviation + close :: "Ctxt \ ty \ tyS" +where + "close \ T \ gen T ((ftv T) - (ftv \))" + +lemma close_eqvt[eqvt]: + fixes pi::"tvar prm" + shows "pi\(close \ T) = close (pi\\) (pi\T)" +by (simp_all only: eqvts) + +text {* Substitution *} + +types Subst = "(tvar\ty) list" + +consts + psubst :: "Subst \ 'a \ 'a" ("_<_>" [100,60] 120) + +abbreviation + subst :: "'a \ tvar \ ty \ 'a" ("_[_::=_]" [100,100,100] 100) +where + "smth[X::=T] \ ([(X,T)])" + +fun + lookup :: "Subst \ tvar \ ty" +where + "lookup [] X = TVar X" +| "lookup ((Y,T)#\) X = (if X=Y then T else lookup \ X)" + +lemma lookup_eqvt[eqvt]: + fixes pi::"tvar prm" + shows "pi\(lookup \ X) = lookup (pi\\) (pi\X)" +by (induct \) (auto simp add: eqvts) + +nominal_primrec (psubst_ty) + "\ = lookup \ X" + "\1 \ T\<^isub>2> = (\1>) \ (\2>)" +by (rule TrueI)+ + +lemma psubst_ty_eqvt[eqvt]: + fixes pi1::"tvar prm" + and \::"Subst" + and T::"ty" + shows "pi1\(\) = (pi1\\)<(pi1\T)>" +by (induct T rule: ty.induct) (simp_all add: eqvts) + +text {* instance *} +inductive + general :: "ty \ tyS \ bool"("_ \ _" [50,51] 50) +where + G_Ty[intro]: "T \ (Ty T)" +| G_All[intro]: "\X\T'; (T::ty) \ S\ \ T[X::=T'] \ \[X].S" + +equivariance general[tvar] + +text{* typing judgements *} +inductive + typing :: "Ctxt \ trm \ ty \ bool" (" _ \ _ : _ " [60,60,60] 60) +where + T_VAR[intro]: "\valid \; (x,S)\set \; T \ S\\ \ \ Var x : T" +| T_APP[intro]: "\\ \ t\<^isub>1 : T\<^isub>1\T\<^isub>2; \ \ t\<^isub>2 : T\<^isub>1\\ \ \ App t\<^isub>1 t\<^isub>2 : T\<^isub>2" +| T_LAM[intro]: "\x\\;((x,Ty T\<^isub>1)#\) \ t : T\<^isub>2\ \ \ \ Lam [x].t : T\<^isub>1\T\<^isub>2" +| T_LET[intro]: "\x\\; \ \ t\<^isub>1 : T\<^isub>1; ((x,close \ T\<^isub>1)#\) \ t\<^isub>2 : T\<^isub>2; set (ftv T\<^isub>1 - ftv \) \* T\<^isub>2\ \ \ \ Let x be t\<^isub>1 in t\<^isub>2 : T\<^isub>2" + +lemma fresh_star_tvar_eqvt[eqvt]: + "(pi::tvar prm) \ ((Xs::tvar set) \* (x::'a::{cp_tvar_tvar,pt_tvar})) = (pi \ Xs) \* (pi \ x)" + by (simp only: pt_fresh_star_bij_ineq(1) [OF pt_tvar_inst pt_tvar_inst at_tvar_inst cp_tvar_tvar_inst] perm_bool) + +equivariance typing[tvar] + +lemma fresh_tvar_trm: "(X::tvar) \ (t::trm)" + by (nominal_induct t rule: trm.strong_induct) (simp_all add: fresh_atm abs_fresh) + +lemma ftv_ty: "supp (T::ty) = set (ftv T)" + by (nominal_induct T rule: ty.strong_induct) (simp_all add: ty.supp supp_atm) + +lemma ftv_tyS: "supp (s::tyS) = set (ftv s)" + by (nominal_induct s rule: tyS.strong_induct) (auto simp add: tyS.supp abs_supp ftv_ty) + +lemma ftv_Ctxt: "supp (\::Ctxt) = set (ftv \)" + apply (induct \) + apply (simp_all add: supp_list_nil supp_list_cons) + apply (case_tac a) + apply (simp add: supp_prod supp_atm ftv_tyS) + done + +lemma ftv_tvars: "supp (Tvs::tvar list) = set Tvs" + by (induct Tvs) (simp_all add: supp_list_nil supp_list_cons supp_atm) + +lemma difference_supp: "((supp ((xs::tvar list) - ys))::tvar set) = supp xs - supp ys" + by (induct xs) (auto simp add: supp_list_nil supp_list_cons ftv_tvars) + +lemma set_supp_eq: "set (xs::tvar list) = supp xs" + by (induct xs) (simp_all add: supp_list_nil supp_list_cons supp_atm) + +nominal_inductive2 typing + avoids T_LET: "set (ftv T\<^isub>1 - ftv \)" + apply (simp add: fresh_star_def fresh_def ftv_Ctxt) + apply (simp add: fresh_star_def fresh_tvar_trm) + apply assumption + apply simp + done + +lemma perm_fresh_fresh_aux: + "\(x,y)\set (pi::tvar prm). x \ z \ y \ z \ pi \ (z::'a::pt_tvar) = z" + apply (induct pi rule: rev_induct) + apply simp + apply (simp add: split_paired_all pt_tvar2) + apply (frule_tac x="(a, b)" in bspec) + apply simp + apply (simp add: perm_fresh_fresh) + done + +lemma freshs_mem: "x \ (S::tvar set) \ S \* z \ x \ z" + by (simp add: fresh_star_def) + +lemma fresh_gen_set: + fixes X::"tvar" + and Xs::"tvar list" + assumes asm: "X\set Xs" + shows "X\gen T Xs" +using asm +apply(induct Xs) +apply(simp) +apply(case_tac "X=a") +apply(simp add: abs_fresh) +apply(simp add: abs_fresh) +done + +lemma close_fresh: + fixes \::"Ctxt" + shows "\(X::tvar)\set ((ftv T) - (ftv \)). X\(close \ T)" +by (simp add: fresh_gen_set) + +lemma gen_supp: "(supp (gen T Xs)::tvar set) = supp T - supp Xs" + by (induct Xs) (auto simp add: supp_list_nil supp_list_cons tyS.supp abs_supp supp_atm) + +lemma minus_Int_eq: "T - (T - U) = T \ U" + by blast + +lemma close_supp: "supp (close \ T) = set (ftv T) \ set (ftv \)" + apply (simp add: gen_supp difference_supp ftv_ty ftv_Ctxt) + apply (simp only: set_supp_eq minus_Int_eq) + done + +lemma better_T_LET: + assumes x: "x\\" + and t1: "\ \ t\<^isub>1 : T\<^isub>1" + and t2: "((x,close \ T\<^isub>1)#\) \ t\<^isub>2 : T\<^isub>2" + shows "\ \ Let x be t\<^isub>1 in t\<^isub>2 : T\<^isub>2" +proof - + have fin: "finite (set (ftv T\<^isub>1 - ftv \))" by simp + obtain pi where pi1: "(pi \ set (ftv T\<^isub>1 - ftv \)) \* (T\<^isub>2, \)" + and pi2: "set pi \ set (ftv T\<^isub>1 - ftv \) \ (pi \ set (ftv T\<^isub>1 - ftv \))" + by (rule at_set_avoiding [OF at_tvar_inst fin fs_tvar1, of "(T\<^isub>2, \)"]) + from pi1 have pi1': "(pi \ set (ftv T\<^isub>1 - ftv \)) \* \" + by (simp add: fresh_star_prod) + have Gamma_fresh: "\(x,y)\set pi. x \ \ \ y \ \" + apply (rule ballI) + apply (simp add: split_paired_all) + apply (drule subsetD [OF pi2]) + apply (erule SigmaE) + apply (drule freshs_mem [OF _ pi1']) + apply (simp add: ftv_Ctxt [symmetric] fresh_def) + done + have close_fresh': "\(x, y)\set pi. x \ close \ T\<^isub>1 \ y \ close \ T\<^isub>1" + apply (rule ballI) + apply (simp add: split_paired_all) + apply (drule subsetD [OF pi2]) + apply (erule SigmaE) + apply (drule bspec [OF close_fresh]) + apply (drule freshs_mem [OF _ pi1']) + apply (simp add: fresh_def close_supp ftv_Ctxt) + done + note x + moreover from Gamma_fresh perm_boolI [OF t1, of pi] + have "\ \ t\<^isub>1 : pi \ T\<^isub>1" + by (simp add: perm_fresh_fresh_aux eqvts fresh_tvar_trm) + moreover from t2 close_fresh' + have "(x,(pi \ close \ T\<^isub>1))#\ \ t\<^isub>2 : T\<^isub>2" + by (simp add: perm_fresh_fresh_aux) + with Gamma_fresh have "(x,close \ (pi \ T\<^isub>1))#\ \ t\<^isub>2 : T\<^isub>2" + by (simp add: close_eqvt perm_fresh_fresh_aux) + moreover from pi1 Gamma_fresh + have "set (ftv (pi \ T\<^isub>1) - ftv \) \* T\<^isub>2" + by (simp only: eqvts fresh_star_prod perm_fresh_fresh_aux) + ultimately show ?thesis by (rule T_LET) +qed end