# HG changeset patch # User urbanc # Date 1209687427 -7200 # Node ID 805eece49928242ecd0e664da4dd9945b28a934c # Parent fba4995cb0f9ebcc409a65137e733178457248c6 extended to be a library of general facts about the lambda calculus diff -r fba4995cb0f9 -r 805eece49928 src/HOL/Nominal/Examples/Lam_Funs.thy --- a/src/HOL/Nominal/Examples/Lam_Funs.thy Fri May 02 02:16:10 2008 +0200 +++ b/src/HOL/Nominal/Examples/Lam_Funs.thy Fri May 02 02:17:07 2008 +0200 @@ -4,7 +4,10 @@ imports "../Nominal" begin -text {* Defines some functions over lambda-terms *} +text {* + Provides useful definitions for reasoning + with lambda-terms. +*} atom_decl name @@ -13,15 +16,15 @@ | App "lam" "lam" | Lam "\name\lam" ("Lam [_]._" [100,100] 100) -text {* Depth of a lambda-term *} +text {* The depth of a lambda-term. *} consts depth :: "lam \ nat" nominal_primrec - "depth (Var x) = (1::nat)" + "depth (Var x) = 1" "depth (App t1 t2) = (max (depth t1) (depth t2)) + 1" - "depth (Lam [a].t) = (depth t) + (1::nat)" + "depth (Lam [a].t) = (depth t) + 1" apply(finite_guess)+ apply(rule TrueI)+ apply(simp add: fresh_nat) @@ -29,11 +32,10 @@ done text {* - Free variables of a lambda-term. The complication of this - function is the fact that it returns a name set, which is - not automatically a finitely supported type. So we have to - prove the invariant that frees always returns a finite set - of names. + The free variables of a lambda-term. A complication in this + function arises from the fact that it returns a name set, which + is not a finitely supported type. Therefore we have to prove + the invariant that frees always returns a finite set of names. *} consts @@ -48,36 +50,65 @@ apply(simp add: fresh_def) apply(simp add: supp_of_fin_sets[OF pt_name_inst, OF at_name_inst, OF fs_at_inst[OF at_name_inst]]) apply(simp add: supp_atm) -apply(force) +apply(blast) apply(fresh_guess)+ done +text {* + We can avoid the definition of frees by + using the build in notion of support. +*} + lemma frees_equals_support: shows "frees t = supp t" by (nominal_induct t rule: lam.induct) (simp_all add: lam.supp supp_atm abs_supp) -text {* Capture-avoiding substitution *} +text {* Parallel and single capture-avoiding substitution. *} + +fun + lookup :: "(name\lam) list \ name \ lam" +where + "lookup [] x = Var x" +| "lookup ((y,e)#\) x = (if x=y then e else lookup \ x)" + +lemma lookup_eqvt[eqvt]: + fixes pi::"name prm" + and \::"(name\lam) list" + and X::"name" + shows "pi\(lookup \ X) = lookup (pi\\) (pi\X)" +by (induct \) (auto simp add: eqvts) consts - subst :: "lam \ name \ lam \ lam" ("_[_::=_]" [100,100,100] 100) - + psubst :: "(name\lam) list \ lam \ lam" ("_<_>" [95,95] 105) + nominal_primrec - "(Var x)[y::=t'] = (if x=y then t' else (Var x))" - "(App t1 t2)[y::=t'] = App (t1[y::=t']) (t2[y::=t'])" - "x\(y,t') \ (Lam [x].t)[y::=t'] = Lam [x].(t[y::=t'])" + "\<(Var x)> = (lookup \ x)" + "\<(App e\<^isub>1 e\<^isub>2)> = App (\1>) (\2>)" + "x\\ \ \<(Lam [x].e)> = Lam [x].(\)" apply(finite_guess)+ apply(rule TrueI)+ -apply(simp add: abs_fresh) +apply(simp add: abs_fresh)+ apply(fresh_guess)+ done -lemma subst_eqvt[eqvt]: - fixes pi:: "name prm" - shows "pi\(t1[b::=t2]) = (pi\t1)[(pi\b)::=(pi\t2)]" -apply(nominal_induct t1 avoiding: b t2 rule: lam.induct) -apply(auto simp add: perm_bij fresh_prod fresh_atm fresh_bij) -done +lemma psubst_eqvt[eqvt]: + fixes pi::"name prm" + and t::"lam" + shows "pi\(\) = (pi\\)<(pi\t)>" +by (nominal_induct t avoiding: \ rule: lam.induct) + (simp_all add: eqvts fresh_bij) + +abbreviation + subst :: "lam \ name \ lam \ lam" ("_[_::=_]" [100,100,100] 100) +where + "t[x::=t'] \ ([(x,t')])" + +lemma subst[simp]: + shows "(Var x)[y::=t'] = (if x=y then t' else (Var x))" + and "(App t1 t2)[y::=t'] = App (t1[y::=t']) (t2[y::=t'])" + and "x\(y,t') \ (Lam [x].t)[y::=t'] = Lam [x].(t[y::=t'])" +by (simp_all add: fresh_list_cons fresh_list_nil) lemma subst_supp: shows "supp(t1[a::=t2]) \ (((supp(t1)-{a})\supp(t2))::name set)" @@ -86,44 +117,43 @@ apply(blast)+ done -text{* Parallel substitution *} - -consts - psubst :: "(name\lam) list \ lam \ lam" ("_<_>" [100,100] 900) - -fun - lookup :: "(name\lam) list \ name \ lam" -where - "lookup [] x = Var x" -| "lookup ((y,T)#\) x = (if x=y then T else lookup \ x)" +text {* + Contexts - lambda-terms with a single hole. + Note that the lambda case in contexts does not bind a + name, even if we introduce the notation [_]._ for CLam. +*} +nominal_datatype clam = + Hole ("\" 1000) + | CAppL "clam" "lam" + | CAppR "lam" "clam" + | CLam "name" "clam" ("CLam [_]._" [100,100] 100) -lemma lookup_eqvt[eqvt]: - fixes pi::"name prm" - shows "pi\(lookup \ x) = lookup (pi\\) (pi\x)" -by (induct \) (auto simp add: perm_bij) +text {* Filling a lambda-term into a context. *} -lemma lookup_fresh: - fixes z::"name" - assumes "z\\" "z\x" - shows "z\ lookup \ x" -using assms -by (induct rule: lookup.induct) (auto simp add: fresh_list_cons) - -lemma lookup_fresh': - assumes "z\\" - shows "lookup \ z = Var z" -using assms -by (induct rule: lookup.induct) - (auto simp add: fresh_list_cons fresh_prod fresh_atm) +consts + filling :: "clam \ lam \ lam" ("_\_\" [100,100] 100) nominal_primrec - "\<(Var x)> = (lookup \ x)" - "\<(App t1 t2)> = App (\) (\)" - "x\\\\<(Lam [x].t)> = Lam [x].(\)" -apply(finite_guess)+ -apply(rule TrueI)+ -apply(simp add: abs_fresh) -apply(fresh_guess)+ -done + "\\t\ = t" + "(CAppL E t')\t\ = App (E\t\) t'" + "(CAppR t' E)\t\ = App t' (E\t\)" + "(CLam [x].E)\t\ = Lam [x].(E\t\)" +by (rule TrueI)+ + +text {* Composition od two contexts *} + +consts + clam_compose :: "clam \ clam \ clam" ("_ \ _" [100,100] 100) + +nominal_primrec + "\ \ E' = E'" + "(CAppL E t') \ E' = CAppL (E \ E') t'" + "(CAppR t' E) \ E' = CAppR t' (E \ E')" + "(CLam [x].E) \ E' = CLam [x].(E \ E')" +by (rule TrueI)+ + +lemma clam_compose: + shows "(E1 \ E2)\t\ = E1\E2\t\\" +by (induct E1 rule: clam.weak_induct) (auto) end