# HG changeset patch # User urbanc # Date 1170432976 -3600 # Node ID f76f187c91f969fe639decf8137a31802956909f # Parent bdec4a82f385e51a14c4b0147455df14f25535d6 added an infrastructure that allows the user to declare lemmas to be equivariance lemmas; the intention is to use these lemmas in automated tools but also can be employed by the user diff -r bdec4a82f385 -r f76f187c91f9 src/HOL/Nominal/Examples/Crary.thy --- a/src/HOL/Nominal/Examples/Crary.thy Fri Feb 02 15:47:58 2007 +0100 +++ b/src/HOL/Nominal/Examples/Crary.thy Fri Feb 02 17:16:16 2007 +0100 @@ -102,7 +102,7 @@ v_nil[intro]: "valid []" | v_cons[intro]: "\valid \;a\\\ \ valid ((a,\)#\)" -lemma valid_eqvt: +lemma valid_eqvt[eqvt]: fixes pi:: "name prm" assumes a: "valid \" shows "valid (pi\\)" @@ -129,10 +129,10 @@ using assms by (induct) (auto) -lemma typing_eqvt : +lemma typing_eqvt[eqvt]: fixes pi::"name prm" assumes "\ \ t : T" - shows "(pi\\) \ (pi\t) : T" + shows "(pi\\) \ (pi\t) : (pi\T)" using assms apply(induct) apply(auto simp add: fresh_bij set_eqvt valid_eqvt) @@ -163,29 +163,28 @@ and x :: "'a::fs_name" assumes a: "\ \ e : T" and a1: "\\ x T c. \valid \; (x,T)\set \\ \ P c \ (Var x) T" - and a2: "\\ e1 T1 T2 e2 c. - \\ \ e1 : T1\T2 ; \c. P c \ e1 (T1\T2); \ \ e2 : T1 ; \c. P c \ e2 T1\ + and a2: "\\ e1 T1 T2 e2 c. \\c. P c \ e1 (T1\T2); \c. P c \ e2 T1\ \ P c \ (App e1 e2) T2" - and a3: "\x \ T1 t T2 c. - \x\(\,c); (x,T1)#\ \ t : T2 ; \c. P c ((x,T1)#\) t T2\ + and a3: "\x \ T1 t T2 c.\x\(\,c); \c. P c ((x,T1)#\) t T2\ \ P c \ (Lam [x].t) (T1\T2)" and a4: "\\ n c. valid \ \ P c \ (Const n) TBase" and a5: "\\ c. valid \ \ P c \ Unit TUnit" shows "P c \ e T" proof - - from a have "\(pi::name prm) c. P c (pi\\) (pi\e) T" + from a have "\(pi::name prm) c. P c (pi\\) (pi\e) (pi\T)" proof (induct) case (t_Var \ x T pi c) have "valid \" by fact - then have "valid (pi\\)" by (simp only: valid_eqvt) + then have "valid (pi\\)" by (simp only: eqvt) moreover have "(x,T)\set \" by fact then have "pi\(x,T)\pi\(set \)" by (simp only: pt_set_bij[OF pt_name_inst, OF at_name_inst]) then have "(pi\x,T)\set (pi\\)" by (simp add: set_eqvt) - ultimately show "P c (pi\\) (pi\(Var x)) T" using a1 by simp + ultimately show "P c (pi\\) (pi\(Var x)) (pi\T)" using a1 by simp next case (t_App \ e1 T1 T2 e2 pi c) - thus "P c (pi\\) (pi\(App e1 e2)) T2" using a2 by (simp, blast intro: typing_eqvt) + thus "P c (pi\\) (pi\(App e1 e2)) (pi\T2)" using a2 + by (simp only: eqvt) (blast) next case (t_Lam x \ T1 t T2 pi c) obtain y::"name" where fs: "y\(pi\x,pi\\,pi\t,c)" by (erule exists_fresh[OF fs_name1]) @@ -194,11 +193,8 @@ have f0: "x\\" by fact have f1: "(pi\x)\(pi\\)" using f0 by (simp add: fresh_bij) have f2: "y\?pi'\\" by (auto simp add: pt_name2 fresh_left calc_atm perm_pi_simp) - have pr1: "(x,T1)#\ \ t : T2" by fact - then have "(?pi'\((x,T1)#\)) \ (?pi'\t) : T2" by (simp only: typing_eqvt) - moreover - have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\t) T2" by fact - ultimately have "P c (?pi'\\) (Lam [y].(?pi'\t)) (T1\T2)" using fs f2 a3 + have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\t) (?pi'\T2)" by fact + then have "P c (?pi'\\) (Lam [y].(?pi'\t)) (T1\T2)" using fs f2 a3 by (simp add: calc_atm) then have "P c (?sw\pi\\) (?sw\(Lam [(pi\x)].(pi\t))) (T1\T2)" by (simp del: append_Cons add: calc_atm pt_name2) @@ -206,18 +202,17 @@ by (rule perm_fresh_fresh) (simp_all add: fs f1) moreover have "(?sw\(Lam [(pi\x)].(pi\t))) = Lam [(pi\x)].(pi\t)" by (rule perm_fresh_fresh) (simp_all add: fs f1 fresh_atm abs_fresh) - ultimately show "P c (pi\\) (pi\(Lam [x].t)) (T1\T2)" - by simp + ultimately show "P c (pi\\) (pi\(Lam [x].t)) (pi\T1\T2)" by simp next case (t_Const \ n pi c) - thus "P c (pi\\) (pi\(Const n)) (TBase)" using a4 by (simp, blast intro: valid_eqvt) + thus "P c (pi\\) (pi\(Const n)) (pi\TBase)" using a4 by (simp, blast intro: valid_eqvt) next case (t_Unit \ pi c) - thus "P c (pi\\) (pi\Unit) (TUnit)" using a5 by (simp, blast intro: valid_eqvt) + thus "P c (pi\\) (pi\Unit) (pi\TUnit)" using a5 by (simp, blast intro: valid_eqvt) qed - then have "P c (([]::name prm)\\) (([]::name prm)\e) T" by blast + then have "P c (([]::name prm)\\) (([]::name prm)\e) (([]::name prm)\T)" by blast then show "P c \ e T" by simp -qed +qed text {* capture-avoiding substitution *} @@ -279,7 +274,7 @@ and "Unit [y::=t'] = Unit" by (simp_all add: fresh_list_cons fresh_list_nil) -lemma subst_eqvt: +lemma subst_eqvt[eqvt]: fixes pi::"name prm" and t::"trm" shows "pi\(t[x::=t']) = (pi\t)[(pi\x)::=(pi\t')]" @@ -371,13 +366,13 @@ shows "valid \" using assms by (induct,auto elim:typing_valid) -lemma equiv_def_eqvt: +lemma equiv_def_eqvt[eqvt]: fixes pi::"name prm" assumes a: "\ \ s == t : T" - shows "(pi\\) \ (pi\s) == (pi\t) : T" + shows "(pi\\) \ (pi\s) == (pi\t) : (pi\T)" using a apply(induct) -apply(auto intro: typing_eqvt valid_eqvt simp add: fresh_bij subst_eqvt) +apply(auto intro: typing_eqvt valid_eqvt simp add: fresh_bij subst_eqvt simp del: perm_ty) apply(rule_tac x="pi\x" in Q_Ext) apply(simp add: fresh_bij)+ done @@ -387,46 +382,39 @@ fixes c::"'a::fs_name" assumes a0: "\ \ s == t : T" and a1: "\\ t T c. \ \ t : T \ P c \ t t T" - and a2: "\\ t s T c. \\ \ t == s : T; \d. P d \ t s T\ \ P c \ s t T" - and a3: "\\ s t T u c. - \\ \ s == t : T; \d. P d \ s t T; \ \ t == u : T; \d. P d \ t u T\ + and a2: "\\ t s T c. \\d. P d \ t s T\ \ P c \ s t T" + and a3: "\\ s t T u c. \\d. P d \ s t T; \d. P d \ t u T\ \ P c \ s u T" - and a4: "\x \ T1 s2 t2 T2 c. \x\\; x\c; (x,T1)#\ \ s2 == t2 : T2; \d. P d ((x,T1)#\) s2 t2 T2\ + and a4: "\x \ T1 s2 t2 T2 c. \x\\; x\c; \d. P d ((x,T1)#\) s2 t2 T2\ \ P c \ (Lam [x].s2) (Lam [x].t2) (T1\T2)" - and a5: "\\ s1 t1 T1 T2 s2 t2 c. - \\ \ s1 == t1 : T1\T2; \d. P d \ s1 t1 (T1\T2); - \ \ s2 == t2 : T1; \d. P d \ s2 t2 T1\ \ P c \ (App s1 s2) (App t1 t2) T2" + and a5: "\\ s1 t1 T1 T2 s2 t2 c. \\d. P d \ s1 t1 (T1\T2); \d. P d \ s2 t2 T1\ + \ P c \ (App s1 s2) (App t1 t2) T2" and a6: "\x \ T1 s12 t12 T2 s2 t2 c. - \x\(\,s2,t2); x\c; (x,T1)#\ \ s12 == t12 : T2; \d. P d ((x,T1)#\) s12 t12 T2; - \ \ s2 == t2 : T1; \d. P d \ s2 t2 T1\ + \x\(\,s2,t2); x\c; \d. P d ((x,T1)#\) s12 t12 T2; \d. P d \ s2 t2 T1\ \ P c \ (App (Lam [x].s12) s2) (t12[x::=t2]) T2" and a7: "\x \ s t T1 T2 c. - \x\(\,s,t); (x,T1)#\ \ App s (Var x) == App t (Var x) : T2; - \d. P d ((x,T1)#\) (App s (Var x)) (App t (Var x)) T2\ + \x\(\,s,t); \d. P d ((x,T1)#\) (App s (Var x)) (App t (Var x)) T2\ \ P c \ s t (T1\T2)" shows "P c \ s t T" proof - - from a0 have "\(pi::name prm) c. P c (pi\\) (pi\s) (pi\t) T" + from a0 have "\(pi::name prm) c. P c (pi\\) (pi\s) (pi\t) (pi\T)" proof(induct) case (Q_Refl \ t T pi c) - then show "P c (pi\\) (pi\t) (pi\t) T" using a1 by (simp add: typing_eqvt) + then show "P c (pi\\) (pi\t) (pi\t) (pi\T)" using a1 by (simp only: eqvt) next case (Q_Symm \ t s T pi c) - then show "P c (pi\\) (pi\s) (pi\t) T" using a2 by (simp only: equiv_def_eqvt) + then show "P c (pi\\) (pi\s) (pi\t) (pi\T)" using a2 by (simp only: equiv_def_eqvt) next case (Q_Trans \ s t T u pi c) - then show " P c (pi\\) (pi\s) (pi\u) T" using a3 by (blast intro: equiv_def_eqvt) + then show " P c (pi\\) (pi\s) (pi\u) (pi\T)" using a3 by (blast intro: equiv_def_eqvt) next case (Q_App \ s1 t1 T1 T2 s2 t2 pi c) - then show "P c (pi\\) (pi\App s1 s2) (pi\App t1 t2) T2" using a5 - by (simp, blast intro: equiv_def_eqvt) + then show "P c (pi\\) (pi\App s1 s2) (pi\App t1 t2) (pi\T2)" using a5 + by (simp only: eqvt) (blast) next case (Q_Ext x \ s t T1 T2 pi c) - then show "P c (pi\\) (pi\s) (pi\t) (T1\T2)" - apply(auto intro!: a7 simp add: fresh_bij) - apply(drule equiv_def_eqvt) - apply(simp) - done + then show "P c (pi\\) (pi\s) (pi\t) (pi\T1\T2)" + by (auto intro!: a7 simp add: fresh_bij) next case (Q_Abs x \ T1 s2 t2 T2 pi c) obtain y::"name" where fs: "y\(pi\x,pi\s2,pi\t2,pi\\,c)" by (rule exists_fresh[OF fs_name1]) @@ -435,13 +423,9 @@ have f1: "x\\" by fact have f2: "(pi\x)\(pi\\)" using f1 by (simp add: fresh_bij) have f3: "y\?pi'\\" using f1 by (auto simp add: pt_name2 fresh_left calc_atm perm_pi_simp) - have pr1: "(x,T1)#\ \ s2 == t2 : T2" by fact - then have "?pi'\((x,T1)#\) \ (?pi'\s2) == (?pi'\t2) : T2" by (rule equiv_def_eqvt) - then have "((y,T1)#(?pi'\\)) \ (?pi'\s2) == (?pi'\t2) : T2" by (simp add: calc_atm) - moreover - have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\s2) (?pi'\t2) T2" by fact + have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\s2) (?pi'\t2) (?pi'\T2)" by fact then have "\c. P c ((y,T1)#(?pi'\\)) (?pi'\s2) (?pi'\t2) T2" by (simp add: calc_atm) - ultimately have "P c (?pi'\\) (?pi'\Lam [x].s2) (?pi'\Lam [x].t2) (T1\T2)" using a4 f3 fs + then have "P c (?pi'\\) (?pi'\Lam [x].s2) (?pi'\Lam [x].t2) (T1\T2)" using a4 f3 fs by (simp add: calc_atm) then have "P c (?sw\pi\\) (?sw\Lam [(pi\x)].(pi\s2)) (?sw\Lam [(pi\x)].(pi\t2)) (T1\T2)" by (simp del: append_Cons add: calc_atm pt_name2) @@ -452,7 +436,7 @@ moreover have "(?sw\(Lam [(pi\x)].(pi\t2))) = Lam [(pi\x)].(pi\t2)" by (rule perm_fresh_fresh) (simp_all add: fs f2 abs_fresh) ultimately have "P c (pi\\) (Lam [(pi\x)].(pi\s2)) (Lam [(pi\x)].(pi\t2)) (T1\T2)" by simp - then show "P c (pi\\) (pi\Lam [x].s2) (pi\Lam [x].t2) (T1\T2)" by simp + then show "P c (pi\\) (pi\Lam [x].s2) (pi\Lam [x].t2) (pi\T1\T2)" by simp next case (Q_Beta x \ s2 t2 T1 s12 t12 T2 pi c) obtain y::"name" where fs: "y\(pi\x,pi\s12,pi\t12,pi\s2,pi\t2,pi\\,c)" @@ -463,19 +447,12 @@ have f2: "(pi\x)\(pi\(\,s2,t2))" using f1 by (simp add: fresh_bij) have f3: "y\(?pi'\(\,s2,t2))" using f1 by (auto simp add: pt_name2 fresh_left calc_atm perm_pi_simp fresh_prod) - have pr1: "(x,T1)#\ \ s12 == t12 : T2" by fact - then have "?pi'\((x,T1)#\) \ (?pi'\s12) == (?pi'\t12) : T2" by (rule equiv_def_eqvt) - then have "((y,T1)#(?pi'\\)) \ (?pi'\s12) == (?pi'\t12) : T2" by (simp add: calc_atm) - moreover - have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\s12) (?pi'\t12) T2" by fact - then have "\c. P c ((y,T1)#(?pi'\\)) (?pi'\s12) (?pi'\t12) T2" by (simp add: calc_atm) + have ih1: "\c. P c (?pi'\((x,T1)#\)) (?pi'\s12) (?pi'\t12) (?pi'\T2)" by fact + then have "\c. P c ((y,T1)#(?pi'\\)) (?pi'\s12) (?pi'\t12) (?pi'\T2)" by (simp add: calc_atm) moreover - have pr2: "\ \ s2 == t2 : T1" by fact - then have "(?pi'\\) \ (?pi'\s2) == (?pi'\t2) : T1" by (rule equiv_def_eqvt) - moreover - have ih2: "\c. P c (?pi'\\) (?pi'\s2) (?pi'\t2) T1" by fact - ultimately have "P c (?pi'\\) (?pi'\(App (Lam [x].s12) s2)) (?pi'\(t12[x::=t2])) T2" - using a6 f3 fs by (simp add: subst_eqvt calc_atm) + have ih2: "\c. P c (?pi'\\) (?pi'\s2) (?pi'\t2) (?pi'\T1)" by fact + ultimately have "P c (?pi'\\) (?pi'\(App (Lam [x].s12) s2)) (?pi'\(t12[x::=t2])) (?pi'\T2)" + using a6 f3 fs by (force simp add: subst_eqvt calc_atm del: perm_ty) then have "P c (?sw\pi\\) (?sw\(App (Lam [(pi\x)].(pi\s12)) (pi\s2))) (?sw\((pi\t12)[(pi\x)::=(pi\t2)])) T2" by (simp del: append_Cons add: calc_atm pt_name2 subst_eqvt) @@ -488,9 +465,9 @@ (simp_all add: fs[simplified] f2[simplified] fresh_subst fresh_subst'') ultimately have "P c (pi\\) (App (Lam [(pi\x)].(pi\s12)) (pi\s2)) ((pi\t12)[(pi\x)::=(pi\t2)]) T2" by simp - then show "P c (pi\\) (pi\App (Lam [x].s12) s2) (pi\t12[x::=t2]) T2" by (simp add: subst_eqvt) + then show "P c (pi\\) (pi\App (Lam [x].s12) s2) (pi\t12[x::=t2]) (pi\T2)" by (simp add: subst_eqvt) qed - then have "P c (([]::name prm)\\) (([]::name prm)\s) (([]::name prm)\t) T" by blast + then have "P c (([]::name prm)\\) (([]::name prm)\s) (([]::name prm)\t) (([]::name prm)\T)" by blast then show "P c \ s t T" by simp qed @@ -538,7 +515,7 @@ using a by (induct) (auto simp add: subst_eqvt fresh_bij) -lemma whn_eqvt: +lemma whn_eqvt[eqvt]: fixes pi::"name prm" assumes a: "t \ t'" shows "(pi\t) \ (pi\t')" @@ -568,10 +545,10 @@ | QAP_App[intro]: "\\ \ p \ q : T1 \ T2; \ \ s <=> t : T1 \ \ \ \ App p s \ App q t : T2" | QAP_Const[intro]: "valid \ \ \ \ Const n \ Const n : TBase" -lemma alg_equiv_alg_path_equiv_eqvt: +lemma alg_equiv_alg_path_equiv_eqvt[eqvt]: fixes pi::"name prm" - shows "\ \ s <=> t : T \ (pi\\) \ (pi\s) <=> (pi\t) : T" - and "\ \ p \ q : T \ (pi\\) \ (pi\p) \ (pi\q) : T" + shows "\ \ s <=> t : T \ (pi\\) \ (pi\s) <=> (pi\t) : (pi\T)" + and "\ \ p \ q : T \ (pi\\) \ (pi\p) \ (pi\q) : (pi\T)" apply(induct rule: alg_equiv_alg_path_equiv.inducts) apply(auto intro: whn_eqvt simp add: fresh_bij valid_eqvt) apply(rule_tac x="pi\x" in QAT_Arrow) @@ -606,7 +583,7 @@ then show "\c (pi::name prm). P1 c (pi\\) (pi\s) (pi\t) TBase" apply(auto) apply(rule_tac p="pi\q" and q="pi\p" in a1) - apply(simp_all add: whn_eqvt alg_equiv_alg_path_equiv_eqvt) + apply(simp_all add: whn_eqvt alg_equiv_alg_path_equiv_eqvt[simplified]) done next case (QAT_Arrow x \ s t T1 T2) @@ -623,8 +600,8 @@ by (simp only: pt_name2 fresh_left, auto simp add: perm_pi_simp calc_atm) then have f3': "y\?pi'\\" "y\?pi'\s" "y\?pi'\t" by (auto simp add: fresh_prod) have pr1: "(x,T1)#\ \ App s (Var x) <=> App t (Var x) : T2" by fact - then have "(?pi'\((x,T1)#\)) \ (?pi'\(App s (Var x))) <=> (?pi'\(App t (Var x))) : T2" - by (simp only: alg_equiv_alg_path_equiv_eqvt) + then have "(?pi'\((x,T1)#\)) \ (?pi'\(App s (Var x))) <=> (?pi'\(App t (Var x))) : (?pi'\T2)" + by (rule alg_equiv_alg_path_equiv_eqvt) then have "(y,T1)#(?pi'\\) \ (App (?pi'\s) (Var y)) <=> (App (?pi'\t) (Var y)) : T2" by (simp add: calc_atm) moreover @@ -659,7 +636,7 @@ next case (QAP_App \ p q T1 T2 s t) then show "\c (pi::name prm). P2 c (pi\\) (pi\App p s) (pi\App q t) T2" - by (auto intro!: a5 simp add: alg_equiv_alg_path_equiv_eqvt) + by (auto intro!: a5 simp add: alg_equiv_alg_path_equiv_eqvt[simplified]) next case (QAP_Const \ n) then show "\c (pi::name prm). P2 c (pi\\) (pi\Const n) (pi\Const n) TBase" @@ -724,7 +701,6 @@ proof (nominal_induct \ s t T and \ s t T avoiding: \' rule: alg_equiv_alg_path_equiv_strong_inducts) case (QAT_Arrow x \ s t T1 T2 \') have fs:"x\\" "x\s" "x\t" by fact - have h1:"(x,T1)#\ \ App s (Var x) <=> App t (Var x) : T2" by fact have h2:"\\\'" by fact have ih:"\\'. \(x,T1)#\ \ \'\ \ \' \ App s (Var x) <=> App t (Var x) : T2" by fact have "x\\'" by fact @@ -984,7 +960,8 @@ have "(pi\((x,T1)#\)) \ pi \ (App s (Var x)) <=> pi \ (App t (Var x)) : T2" by fact then have "(pi\((x,T1)#\)) \ (App (pi\s) (Var (pi\x))) <=> (App (pi\t) (Var (pi\x))) : T2" by auto moreover have "pi\((x,T1)#\) = (pi\x,pi\T1)#(pi\\)" by auto - ultimately have "((pi\x,T1)#(pi\\)) \ (App (pi\s) (Var (pi\x))) <=> (App (pi\t) (Var (pi\x))) : T2" using perm_ty by auto + ultimately have "((pi\x,T1)#(pi\\)) \ (App (pi\s) (Var (pi\x))) <=> (App (pi\t) (Var (pi\x))) : T2" + using perm_ty by auto then show ?case using h by auto qed (auto elim:whn_eqvt valid_eqvt) @@ -1271,7 +1248,6 @@ case (Q_Abs x \ T1 s2 t2 T2 \' \ \) have fs:"x\\" by fact have fs2: "x\\" "x\\" by fact - have h1:"(x,T1)#\ \ s2 == t2 : T2" by fact have h2:"\' \ \ is \ over \" by fact have ih:"\\' \ \. \' \ \ is \ over (x,T1)#\ \ \' \ \ is \ : T2" by fact { diff -r bdec4a82f385 -r f76f187c91f9 src/HOL/Nominal/Examples/Weakening.thy --- a/src/HOL/Nominal/Examples/Weakening.thy Fri Feb 02 15:47:58 2007 +0100 +++ b/src/HOL/Nominal/Examples/Weakening.thy Fri Feb 02 17:16:16 2007 +0100 @@ -32,7 +32,7 @@ v1[intro]: "valid []" | v2[intro]: "\valid \;a\\\\ valid ((a,\)#\)" -lemma eqvt_valid: +lemma eqvt_valid[eqvt]: fixes pi:: "name prm" assumes a: "valid \" shows "valid (pi\\)" @@ -40,6 +40,8 @@ by (induct) (auto simp add: fresh_bij) +thm eqvt + text{* typing judgements *} inductive2 typing :: "(name\ty) list\lam\ty\bool" (" _ \ _ : _ " [80,80,80] 80) @@ -48,22 +50,22 @@ | t_App[intro]: "\\ \ t1 : \\\; \ \ t2 : \\\ \ \ App t1 t2 : \" | t_Lam[intro]: "\a\\;((a,\)#\) \ t : \\ \ \ \ Lam [a].t : \\\" -lemma eqvt_typing: +lemma eqvt_typing[eqvt]: fixes pi:: "name prm" assumes a: "\ \ t : \" - shows "(pi\\) \ (pi\t) : \" + shows "(pi\\) \ (pi\t) : (pi\\)" using a proof (induct) case (t_Var \ a \) have "valid (pi\\)" by (rule eqvt_valid) moreover have "(pi\(a,\))\(pi\set \)" by (rule pt_set_bij2[OF pt_name_inst, OF at_name_inst]) - ultimately show "(pi\\) \ (pi\Var a) : \" + ultimately show "(pi\\) \ (pi\Var a) : (pi\\)" using typing.intros by (force simp add: pt_list_set_pi[OF pt_name_inst, symmetric]) next case (t_Lam a \ \ t \) moreover have "(pi\a)\(pi\\)" by (simp add: fresh_bij) - ultimately show "(pi\\) \ (pi\Lam [a].t) :\\\" by force + ultimately show "(pi\\) \ (pi\Lam [a].t) :(pi\\\\)" by force qed (auto) text {* the strong induction principle needs to be derived manually *} @@ -76,26 +78,26 @@ and x :: "'a::fs_name" assumes a: "\ \ t : \" and a1: "\\ a \ x. \valid \; (a,\) \ set \\ \ P x \ (Var a) \" - and a2: "\\ \ \ t1 t2 x. - \\ \ t1 : \\\; (\z. P z \ t1 (\\\)); \ \ t2 : \; (\z. P z \ t2 \)\ + and a2: "\\ \ \ t1 t2 x. \\z. P z \ t1 (\\\); \z. P z \ t2 \\ \ P x \ (App t1 t2) \" - and a3: "\a \ \ \ t x. \a\x; a\\; ((a,\)#\) \ t : \; (\z. P z ((a,\)#\) t \)\ + and a3: "\a \ \ \ t x. \a\x; a\\; \z. P z ((a,\)#\) t \\ \ P x \ (Lam [a].t) (\\\)" shows "P x \ t \" proof - - from a have "\(pi::name prm) x. P x (pi\\) (pi\t) \" + from a have "\(pi::name prm) x. P x (pi\\) (pi\t) (pi\\)" proof (induct) case (t_Var \ a \) have "valid \" by fact - then have "valid (pi\\)" by (rule eqvt_valid) + then have "valid (pi\\)" by (rule eqvt) moreover have "(a,\)\set \" by fact then have "pi\(a,\)\pi\(set \)" by (simp only: pt_set_bij[OF pt_name_inst, OF at_name_inst]) then have "(pi\a,\)\set (pi\\)" by (simp add: pt_list_set_pi[OF pt_name_inst]) - ultimately show "P x (pi\\) (pi\(Var a)) \" using a1 by simp + ultimately show "P x (pi\\) (pi\(Var a)) (pi\\)" using a1 by simp next case (t_App \ t1 \ \ t2) - thus "P x (pi\\) (pi\(App t1 t2)) \" using a2 by (simp, blast intro: eqvt_typing) + thus "P x (pi\\) (pi\(App t1 t2)) (pi\\)" using a2 + by (simp only: eqvt) (blast) next case (t_Lam a \ \ t \) obtain c::"name" where fs: "c\(pi\a,pi\t,pi\\,x)" by (rule exists_fresh[OF fs_name1]) @@ -104,22 +106,18 @@ have f1: "a\\" by fact have f2: "(pi\a)\(pi\\)" using f1 by (simp add: fresh_bij) have f3: "c\?pi'\\" using f1 by (auto simp add: pt_name2 fresh_left calc_atm perm_pi_simp) - have pr1: "((a,\)#\)\t:\" by fact - then have "(?pi'\((a,\)#\)) \ (?pi'\t) : \" by (rule eqvt_typing) - then have "((c,\)#(?pi'\\)) \ (?pi'\t) : \" by (simp add: calc_atm) - moreover - have ih1: "\x. P x (?pi'\((a,\)#\)) (?pi'\t) \" by fact - then have "\x. P x ((c,\)#(?pi'\\)) (?pi'\t) \" by (simp add: calc_atm) - ultimately have "P x (?pi'\\) (Lam [c].(?pi'\t)) (\ \ \)" using a3 f3 fs by simp - then have "P x (?sw\pi\\) (?sw\(Lam [(pi\a)].(pi\t))) (\ \ \)" + have ih1: "\x. P x (?pi'\((a,\)#\)) (?pi'\t) (?pi'\\)" by fact + then have "\x. P x ((c,\)#(?pi'\\)) (?pi'\t) (?pi'\\)" by (simp add: calc_atm) + then have "P x (?pi'\\) (Lam [c].(?pi'\t)) (\\\)" using a3 f3 fs by simp + then have "P x (?sw\pi\\) (?sw\(Lam [(pi\a)].(pi\t))) (\\\)" by (simp del: append_Cons add: calc_atm pt_name2) moreover have "(?sw\(pi\\)) = (pi\\)" by (rule perm_fresh_fresh) (simp_all add: fs f2) moreover have "(?sw\(Lam [(pi\a)].(pi\t))) = Lam [(pi\a)].(pi\t)" by (rule perm_fresh_fresh) (simp_all add: fs f2 abs_fresh) - ultimately show "P x (pi\\) (pi\(Lam [a].t)) (\ \ \)" by (simp only: , simp) + ultimately show "P x (pi\\) (pi\(Lam [a].t)) (pi\\\\)" by (simp) qed - hence "P x (([]::name prm)\\) (([]::name prm)\t) \" by blast + hence "P x (([]::name prm)\\) (([]::name prm)\t) (([]::name prm)\\)" by blast thus "P x \ t \" by simp qed diff -r bdec4a82f385 -r f76f187c91f9 src/HOL/Nominal/Nominal.thy --- a/src/HOL/Nominal/Nominal.thy Fri Feb 02 15:47:58 2007 +0100 +++ b/src/HOL/Nominal/Nominal.thy Fri Feb 02 17:16:16 2007 +0100 @@ -4,6 +4,7 @@ imports Main Infinite_Set uses ("nominal_atoms.ML") + ("nominal_tags.ML") ("nominal_package.ML") ("nominal_induct.ML") ("nominal_permeq.ML") @@ -3006,22 +3007,19 @@ (* setup for the individial atom-kinds *) (* and nominal datatypes *) use "nominal_atoms.ML" +setup "NominalAtoms.setup" + +(******************************************) +(* Setup of the tags: eqvt, fresh and bij *) + +use "nominal_tags.ML" +setup "EqvtRules.setup" +setup "FreshRules.setup" +setup "BijRules.setup" + +(*******************************) (* permutation equality tactic *) use "nominal_permeq.ML"; -use "nominal_package.ML" -setup "NominalAtoms.setup" -setup "NominalPackage.setup" - -(** primitive recursive functions on nominal datatypes **) -use "nominal_primrec.ML" - -(*****************************************) -(* setup for induction principles method *) - -use "nominal_induct.ML"; -method_setup nominal_induct = - {* NominalInduct.nominal_induct_method *} - {* nominal induction *} method_setup perm_simp = {* NominalPermeq.perm_eq_meth *} @@ -3063,4 +3061,22 @@ {* NominalPermeq.fresh_gs_meth_debug *} {* tactic for deciding whether an atom is fresh for something including debugging facilities *} +(*********************************) +(* nominal datatype construction *) +use "nominal_package.ML" +setup "NominalPackage.setup" + +(******************************************************) +(* primitive recursive functions on nominal datatypes *) +use "nominal_primrec.ML" + +(*****************************************) +(* setup for induction principles method *) + +use "nominal_induct.ML"; +method_setup nominal_induct = + {* NominalInduct.nominal_induct_method *} + {* nominal induction *} + + end diff -r bdec4a82f385 -r f76f187c91f9 src/HOL/Nominal/nominal_package.ML --- a/src/HOL/Nominal/nominal_package.ML Fri Feb 02 15:47:58 2007 +0100 +++ b/src/HOL/Nominal/nominal_package.ML Fri Feb 02 17:16:16 2007 +0100 @@ -1104,6 +1104,7 @@ end) atoms; val simp_atts = replicate (length new_type_names) [Simplifier.simp_add]; + val simp_eqvt_atts = replicate (length new_type_names) [Simplifier.simp_add, EqvtRules.eqvt_add]; val (_, thy9) = thy8 |> Theory.add_path big_name |> @@ -1112,7 +1113,7 @@ Theory.parent_path ||>> DatatypeAux.store_thmss_atts "distinct" new_type_names simp_atts distinct_thms ||>> DatatypeAux.store_thmss "constr_rep" new_type_names constr_rep_thmss ||>> - DatatypeAux.store_thmss_atts "perm" new_type_names simp_atts perm_simps' ||>> + DatatypeAux.store_thmss_atts "perm" new_type_names simp_eqvt_atts perm_simps' ||>> DatatypeAux.store_thmss "inject" new_type_names inject_thms ||>> DatatypeAux.store_thmss "supp" new_type_names supp_thms ||>> DatatypeAux.store_thmss_atts "fresh" new_type_names simp_atts fresh_thms ||> diff -r bdec4a82f385 -r f76f187c91f9 src/HOL/Nominal/nominal_tags.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/nominal_tags.ML Fri Feb 02 17:16:16 2007 +0100 @@ -0,0 +1,267 @@ +(* ID: "$Id$" + Authors: Julien Narboux and Christian Urban + + This file introduces the infrastructure for the lemma + declaration "eqvt" "bij" and "fresh". + + By attaching [eqvt] [bij] or [fresh] to a lemma, the lemma gets stored + in a data-slot in the theory context. Possible modifiers + are [tag add] and [tag del] for adding and deleting, + respectively the lemma from the data-slot. +*) + +signature EQVT_RULES = +sig + val print_eqvtset: Proof.context -> unit + val eqvt_add: attribute + val eqvt_del: attribute + val setup: theory -> theory + + val EQVT_DEBUG : bool ref +end; + +structure EqvtRules: EQVT_RULES = +struct + +structure Data = GenericDataFun +( + val name = "HOL/Nominal/eqvt"; + type T = thm list; + val empty = []; + val extend = I; + fun merge _ = Drule.merge_rules; + fun print context rules = + Pretty.writeln (Pretty.big_list "Equivariance lemmas:" + (map (ProofContext.pretty_thm (Context.proof_of context)) rules)); +); + +(* Exception for when a theorem does not conform with form of an equivariance lemma. *) +(* There are two forms: one is an implication (for relations) and the other is an *) +(* equality (for functions). In the implication-case, say P ==> Q, Q must be equal *) +(* to P except that every free variable of Q, say x, is replaced by pi o x. In the *) +(* equality case, say lhs = rhs, the lhs must be of the form pi o t and the rhs must *) +(* be equal to t except that every free variable, say x, is replaced by pi o x. In *) +(* the implicational case it is also checked that the variables and permutation fit *) +(* together, i.e. are of the right "pt_class", so that a stronger version of the *) +(* eqality-lemma can be derived. *) +exception EQVT_FORM; + +val print_eqvtset = Data.print o Context.Proof; + +(* FIXME: should be a function in a library *) +fun mk_permT T = HOLogic.listT (HOLogic.mk_prodT (T, T)); + +val perm_bool = thm "perm_bool"; + +val EQVT_DEBUG = ref false; + +fun tactic (msg,tac) = + if !EQVT_DEBUG + then (EVERY [tac, print_tac ("after "^msg)]) + else tac + +fun tactic_eqvt ctx orig_thm pi typi = + let + val mypi = Thm.cterm_of ctx (Var (pi,typi)) + val mypifree = Thm.cterm_of ctx (Const ("List.rev",typi --> typi) $ Free (fst pi,typi)) + val perm_pi_simp = PureThy.get_thms ctx (Name "perm_pi_simp") + in + EVERY [tactic ("iffI applied",rtac iffI 1), + tactic ("simplifies with orig_thm and perm_bool", + asm_full_simp_tac (HOL_basic_ss addsimps [perm_bool,orig_thm]) 1), + tactic ("applies orig_thm instantiated with rev pi", + dtac (Drule.cterm_instantiate [(mypi,mypifree)] orig_thm) 1), + tactic ("getting rid of all remaining perms", + full_simp_tac (HOL_basic_ss addsimps (perm_bool::perm_pi_simp)) 1)] + end; + +fun get_derived_thm thy hyp concl orig_thm pi typi = + let + val lhs = (Const("Nominal.perm", typi --> HOLogic.boolT --> HOLogic.boolT) $ Var(pi,typi) $ hyp) + val goal_term = Logic.unvarify (HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs,concl))) + val _ = Display.print_cterm (cterm_of thy goal_term) + in + Goal.prove_global thy [] [] goal_term (fn _ => (tactic_eqvt thy orig_thm pi typi)) + end + +(* FIXME: something naughty here, but as long as there is no infrastructure to expose *) +(* the eqvt_thm_list to the user, we have to manually update the context and the *) +(* thm-list eqvt *) +fun update_context flag thms context = + let + val context' = fold (fn thm => Data.map (flag thm)) thms context + in + Context.mapping (snd o PureThy.add_thmss [(("eqvt",Data.get context'),[])]) I context' + end; + +(* replaces every variable, say x, in t with pi o x *) +fun apply_pi trm (pi,typi) = + let + fun only_vars t = + (case t of + Var (n,ty) => (Const ("Nominal.perm",typi --> ty --> ty) $ (Var (pi,typi)) $ (Var (n,ty))) + | _ => t) + in + map_aterms only_vars trm + end; + +(* returns *the* pi which is in front of all variables, provided there *) +(* exists such a pi; otherwise raises EQVT_FORM *) +fun get_pi t thy = + let fun get_pi_aux s = + (case s of + (Const ("Nominal.perm",typrm) $ + (Var (pi,typi as Type("List.list",[Type ("*",[Type (tyatm,[]),_])]))) $ + (Var (n,ty))) => + let + (* FIXME: this should be an operation the library *) + val class_name = (NameSpace.map_base (fn s => "pt_"^s) tyatm) + in + if (Type.of_sort (Sign.tsig_of thy) (ty,[class_name])) + then [(pi,typi)] + else raise EQVT_FORM + end + | Abs (_,_,t1) => get_pi_aux t1 + | (t1 $ t2) => get_pi_aux t1 @ get_pi_aux t2 + | _ => []) + in + (* collect first all pi's in front of variables in t and then use distinct *) + (* to ensure that all pi's must have been the same, i.e. distinct returns *) + (* a singleton-list *) + (case (distinct (op =) (get_pi_aux t)) of + [(pi,typi)] => (pi,typi) + | _ => raise EQVT_FORM) + end; + +(* Either adds a theorem (orig_thm) to or deletes one from the equivaraince *) +(* lemma list depending on flag. To be added the lemma has to satisfy a *) +(* certain form. *) +fun eqvt_add_del_aux flag orig_thm context = + let + val thy = Context.theory_of context + val thms_to_be_added = (case (prop_of orig_thm) of + (* case: eqvt-lemma is of the implicational form *) + (Const("==>", _) $ (Const ("Trueprop",_) $ hyp) $ (Const ("Trueprop",_) $ concl)) => + let + val (pi,typi) = get_pi concl thy + in + if (apply_pi hyp (pi,typi) = concl) + then + (warning ("equivariance lemma of the relational form"); + [orig_thm, get_derived_thm thy hyp concl orig_thm pi typi]) + else raise EQVT_FORM + end + (* case: eqvt-lemma is of the equational form *) + | (Const ("Trueprop", _) $ (Const ("op =", _) $ + (Const ("Nominal.perm",_) $ Var (pi,typi) $ lhs) $ rhs)) => + (if (apply_pi lhs (pi,typi)) = rhs + then [orig_thm] + else raise EQVT_FORM) + | _ => raise EQVT_FORM) + in + update_context flag thms_to_be_added context + end + handle EQVT_FORM => + error (string_of_thm orig_thm ^ " does not comply with the form of an equivariance lemma.") + +val eqvt_add = Thm.declaration_attribute (eqvt_add_del_aux Drule.add_rule); +val eqvt_del = Thm.declaration_attribute (eqvt_add_del_aux Drule.del_rule); + +val setup = + Data.init #> + Attrib.add_attributes [("eqvt", Attrib.add_del_args eqvt_add eqvt_del, "equivariance rules")]; + +end; + + + +signature BIJ_RULES = +sig + val print_bijset: Proof.context -> unit + val bij_add: attribute + val bij_del: attribute + val setup: theory -> theory +end; + +structure BijRules: BIJ_RULES = +struct + +structure Data = GenericDataFun +( + val name = "HOL/Nominal/bij"; + type T = thm list; + val empty = []; + val extend = I; + fun merge _ = Drule.merge_rules; + fun print context rules = + Pretty.writeln (Pretty.big_list "Bijection lemmas:" + (map (ProofContext.pretty_thm (Context.proof_of context)) rules)); +); + +val print_bijset = Data.print o Context.Proof; + +fun bij_add_del_aux f = fn th => fn context => + let val new_context = Data.map (f th) context + in + Context.mapping (snd o PureThy.add_thmss [(("bij",Data.get new_context),[])]) I new_context + end + +val bij_add = Thm.declaration_attribute (bij_add_del_aux Drule.add_rule); +val bij_del = Thm.declaration_attribute (bij_add_del_aux Drule.del_rule); + +val setup = + Data.init #> + Attrib.add_attributes [("bij", Attrib.add_del_args bij_add bij_del, "bijection rules")]; + +end; + + +signature FRESH_RULES = +sig + val print_freshset: Proof.context -> unit + val fresh_add: attribute + val fresh_del: attribute + val setup: theory -> theory +end; + +structure FreshRules: FRESH_RULES = +struct + +structure Data = GenericDataFun +( + val name = "HOL/Nominal/fresh"; + type T = thm list; + val empty = []; + val extend = I; + fun merge _ = Drule.merge_rules; + fun print context rules = + Pretty.writeln (Pretty.big_list "Freshness lemmas:" + (map (ProofContext.pretty_thm (Context.proof_of context)) rules)); +); + +val print_freshset = Data.print o Context.Proof; + +fun fresh_add_del_aux f = fn th => fn context => + let val new_context = Data.map (f th) context + in + Context.mapping (snd o PureThy.add_thmss [(("fresh",Data.get new_context),[])]) I new_context + end + +val fresh_add = Thm.declaration_attribute (fresh_add_del_aux Drule.add_rule); +val fresh_del = Thm.declaration_attribute (fresh_add_del_aux Drule.del_rule); + +val setup = + Data.init #> + Attrib.add_attributes [("fresh", Attrib.add_del_args fresh_add fresh_del, "freshness rules")]; + +end; + +(* Thm.declaration_attribute is of type (thm -> Context.generic -> Context.generic) -> attribute *) + +(* Thm.declaration_attribute has type (thm -> Context.generic -> Context.generic) -> attribute *) + +(* Drule.add_rule has type thm -> thm list -> thm list *) + +(* Data.map has type thm list -> thm list -> Context.generic -> Context.generic *) + +(* add_del_args is of type attribute -> attribute -> src -> attribute *) \ No newline at end of file