3 (* Formalisation of weakening using locally nameless *)
4 (* terms; the nominal infrastructure can also derive *)
5 (* strong induction principles for such representations *)
7 (* Authors: Christian Urban and Randy Pollack *)
15 Curry-style lambda terms in locally nameless
16 representation without any binders
18 nominal_datatype llam =
24 text {* definition of vsub - at the moment a bit cumbersome *}
27 "(\<exists>a. t = lPar a) \<or> (\<exists>n. t = lVar n) \<or> (\<exists>t1 t2. t = lApp t1 t2) \<or>
28 (\<exists>t1. t = lLam t1)"
29 by (induct t rule: llam.induct)
30 (auto simp add: llam.inject)
32 consts llam_size :: "llam \<Rightarrow> nat"
35 "llam_size (lPar a) = 1"
36 "llam_size (lVar n) = 1"
37 "llam_size (lApp t1 t2) = 1 + (llam_size t1) + (llam_size t2)"
38 "llam_size (lLam t) = 1 + (llam_size t)"
42 vsub :: "llam \<Rightarrow> nat \<Rightarrow> llam \<Rightarrow> llam"
44 vsub_lPar: "vsub (lPar p) x s = lPar p"
45 | vsub_lVar: "vsub (lVar n) x s = (if n < x then (lVar n)
46 else (if n = x then s else (lVar (n - 1))))"
47 | vsub_lApp: "vsub (lApp t u) x s = (lApp (vsub t x s) (vsub u x s))"
48 | vsub_lLam: "vsub (lLam t) x s = (lLam (vsub t (x + 1) s))"
50 apply(auto simp add: llam.inject)
52 apply(drule_tac x="a" in meta_spec)
55 termination by (relation "measure (llam_size \<circ> fst)") auto
57 lemma vsub_eqvt[eqvt]:
59 shows "pi\<bullet>(vsub t n s) = vsub (pi\<bullet>t) (pi\<bullet>n) (pi\<bullet>s)"
60 by (induct t arbitrary: n rule: llam.induct)
61 (simp_all add: perm_nat_def)
64 freshen :: "llam \<Rightarrow> name \<Rightarrow> llam"
65 "freshen t p \<equiv> vsub t 0 (lPar p)"
67 lemma freshen_eqvt[eqvt]:
69 shows "pi\<bullet>(freshen t p) = freshen (pi\<bullet>t) (pi\<bullet>p)"
70 by (simp add: vsub_eqvt freshen_def perm_nat_def)
76 | TArr "ty" "ty" (infix "\<rightarrow>" 200)
82 by (induct T rule: ty.induct)
83 (simp_all add: fresh_nat)
85 text {* valid contexts *}
87 types cxt = "(name\<times>ty) list"
90 valid :: "cxt \<Rightarrow> bool"
93 | v2[intro]: "\<lbrakk>valid \<Gamma>;a\<sharp>\<Gamma>\<rbrakk>\<Longrightarrow> valid ((a,T)#\<Gamma>)"
98 assumes a: "valid ((a,T)#\<Gamma>)"
99 shows "a\<sharp>\<Gamma> \<and> valid \<Gamma>"
100 using a by (cases) (auto)
102 text {* "weak" typing relation *}
105 typing :: "cxt\<Rightarrow>llam\<Rightarrow>ty\<Rightarrow>bool" (" _ \<turnstile> _ : _ " [60,60,60] 60)
107 t_lPar[intro]: "\<lbrakk>valid \<Gamma>; (x,T)\<in>set \<Gamma>\<rbrakk>\<Longrightarrow> \<Gamma> \<turnstile> lPar x : T"
108 | t_lApp[intro]: "\<lbrakk>\<Gamma> \<turnstile> t1 : T1\<rightarrow>T2; \<Gamma> \<turnstile> t2 : T1\<rbrakk>\<Longrightarrow> \<Gamma> \<turnstile> lApp t1 t2 : T2"
109 | t_lLam[intro]: "\<lbrakk>x\<sharp>t; (x,T1)#\<Gamma> \<turnstile> freshen t x : T2\<rbrakk>\<Longrightarrow> \<Gamma> \<turnstile> lLam t : T1\<rightarrow>T2"
113 lemma typing_implies_valid:
114 assumes a: "\<Gamma> \<turnstile> t : T"
115 shows "valid \<Gamma>"
116 using a by (induct) (auto dest: v2_elim)
119 we have to explicitly state that nominal_inductive should strengthen
120 over the variable x (since x is not a binder)
122 nominal_inductive typing
124 by (auto simp add: fresh_prod dest: v2_elim typing_implies_valid)
126 text {* strong induction principle for typing *}
127 thm typing.strong_induct
129 text {* sub-contexts *}
132 "sub_context" :: "cxt \<Rightarrow> cxt \<Rightarrow> bool" ("_ \<subseteq> _" [60,60] 60)
134 "\<Gamma>1 \<subseteq> \<Gamma>2 \<equiv> \<forall>x T. (x,T)\<in>set \<Gamma>1 \<longrightarrow> (x,T)\<in>set \<Gamma>2"
136 lemma weakening_almost_automatic:
137 fixes \<Gamma>1 \<Gamma>2 :: cxt
138 assumes a: "\<Gamma>1 \<turnstile> t : T"
139 and b: "\<Gamma>1 \<subseteq> \<Gamma>2"
140 and c: "valid \<Gamma>2"
141 shows "\<Gamma>2 \<turnstile> t : T"
143 apply(nominal_induct \<Gamma>1 t T avoiding: \<Gamma>2 rule: typing.strong_induct)
145 apply(drule_tac x="(x,T1)#\<Gamma>2" in meta_spec)
146 apply(auto intro!: t_lLam)
149 lemma weakening_in_more_detail:
150 fixes \<Gamma>1 \<Gamma>2 :: cxt
151 assumes a: "\<Gamma>1 \<turnstile> t : T"
152 and b: "\<Gamma>1 \<subseteq> \<Gamma>2"
153 and c: "valid \<Gamma>2"
154 shows "\<Gamma>2 \<turnstile> t : T"
156 proof(nominal_induct \<Gamma>1 t T avoiding: \<Gamma>2 rule: typing.strong_induct)
157 case (t_lPar \<Gamma>1 x T \<Gamma>2) (* variable case *)
158 have "\<Gamma>1 \<subseteq> \<Gamma>2" by fact
160 have "valid \<Gamma>2" by fact
162 have "(x,T)\<in> set \<Gamma>1" by fact
163 ultimately show "\<Gamma>2 \<turnstile> lPar x : T" by auto
165 case (t_lLam x t T1 \<Gamma>1 T2 \<Gamma>2) (* lambda case *)
166 have vc: "x\<sharp>\<Gamma>2" "x\<sharp>t" by fact+ (* variable convention *)
167 have ih: "\<lbrakk>(x,T1)#\<Gamma>1 \<subseteq> (x,T1)#\<Gamma>2; valid ((x,T1)#\<Gamma>2)\<rbrakk> \<Longrightarrow> (x,T1)#\<Gamma>2 \<turnstile> freshen t x : T2" by fact
168 have "\<Gamma>1 \<subseteq> \<Gamma>2" by fact
169 then have "(x,T1)#\<Gamma>1 \<subseteq> (x,T1)#\<Gamma>2" by simp
171 have "valid \<Gamma>2" by fact
172 then have "valid ((x,T1)#\<Gamma>2)" using vc by (simp add: v2)
173 ultimately have "(x,T1)#\<Gamma>2 \<turnstile> freshen t x : T2" using ih by simp
174 with vc show "\<Gamma>2 \<turnstile> lLam t : T1\<rightarrow>T2" by auto
176 case (t_lApp \<Gamma>1 t1 T1 T2 t2 \<Gamma>2)
177 then show "\<Gamma>2 \<turnstile> lApp t1 t2 : T2" by auto