theory Lambda
imports "Nominal"
begin
atom_decl name
section {* Alpha-Equated Lambda-Terms *}
nominal_datatype lam =
Var "name"
| App "lam" "lam"
| Lam "\<guillemotleft>name\<guillemotright>lam" ("Lam [_]._")
section {* Capture-Avoiding Substitution *}
consts subst :: "lam \<Rightarrow> name \<Rightarrow> lam \<Rightarrow> lam" ("_[_::=_]")
nominal_primrec
"(Var x)[y::=s] = (if x=y then s else (Var x))"
"(App t1 t2)[y::=s] = App (t1[y::=s]) (t2[y::=s])"
"x\<sharp>(y,s) \<Longrightarrow> (Lam [x].t)[y::=s] = Lam [x].(t[y::=s])"
apply(finite_guess)+
apply(rule TrueI)+
apply(simp add: abs_fresh)+
apply(fresh_guess)+
done
lemma subst_eqvt[eqvt]:
fixes pi::"name prm"
shows "pi\<bullet>(t1[x::=t2]) = (pi\<bullet>t1)[(pi\<bullet>x)::=(pi\<bullet>t2)]"
by (nominal_induct t1 avoiding: x t2 rule: lam.strong_induct)
(auto simp add: perm_bij fresh_atm fresh_bij)
lemma forget:
assumes a: "x\<sharp>L"
shows "L[x::=P] = L"
using a
by (nominal_induct L avoiding: x P rule: lam.strong_induct)
(auto simp add: abs_fresh fresh_atm)
lemma fresh_fact:
fixes z::"name"
shows "\<lbrakk>z\<sharp>s; (z=y \<or> z\<sharp>t)\<rbrakk> \<Longrightarrow> z\<sharp>t[y::=s]"
by (nominal_induct t avoiding: z y s rule: lam.strong_induct)
(auto simp add: abs_fresh fresh_prod fresh_atm)
lemma subst_rename:
assumes a: "y\<sharp>t"
shows "t[x::=s] = ([(y,x)]\<bullet>t)[y::=s]"
using a
by (nominal_induct t avoiding: x y s rule: lam.strong_induct)
(auto simp add: calc_atm fresh_atm abs_fresh)
text {*
The purpose of the two lemmas below is to work
around some quirks in Isabelle's handling of
meta_quantifiers and meta_implications.
*}
lemma meta_impCE:
assumes major: "P ==> PROP Q"
and 1: "~ P ==> R"
and 2: "PROP Q ==> R"
shows R
proof (cases P)
assume P
then have "PROP Q" by (rule major)
then show R by (rule 2)
next
assume "~ P"
then show R by (rule 1)
qed
declare meta_allE [elim]
and meta_impCE [elim!]
end