# HG changeset patch # User urbanc # Date 1180597700 -7200 # Node ID f72bc42882eab9ffff444b0085e2d7eae3173fd9 # Parent cb1dbe64a4d54587da2cc933ef20a4e23e11ec7b a theory using locally nameless terms and strong induction principles diff -r cb1dbe64a4d5 -r f72bc42882ea src/HOL/Nominal/Examples/LocalWeakening.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Nominal/Examples/LocalWeakening.thy Thu May 31 09:48:20 2007 +0200 @@ -0,0 +1,174 @@ +(* $Id$ *) + +(* Formalisation of weakening using locally nameless *) +(* terms; the nominal infrastructure can derive *) +(* strong induction principles for such representations *) +(* *) +(* Authors: Christian Urban and Randy Pollack *) +theory LocalWeakening +imports "../Nominal" +begin + +atom_decl name + +(* Curry-style lambda terms in locally nameless *) +(* representation without any binders *) +nominal_datatype llam = + lPar "name" + | lVar "nat" + | lApp "llam" "llam" + | lLam "llam" + +lemma llam_cases: + "(\a. t = lPar a) \ (\n. t = lVar n) \ (\t1 t2. t = lApp t1 t2) \ + (\t1. t = lLam t1)" +by (induct t rule: llam.weak_induct) + (auto simp add: llam.inject) + +consts llam_size :: "llam \ nat" + +nominal_primrec + "llam_size (lPar a) = 1" + "llam_size (lVar n) = 1" + "llam_size (lApp t1 t2) = 1 + (llam_size t1) + (llam_size t2)" + "llam_size (lLam t) = 1 + (llam_size t)" +by (rule TrueI)+ + +function + vsub :: "llam \ nat \ llam \ llam" +where + vsub_lPar: "vsub (lPar p) x s = lPar p" + | vsub_lVar: "vsub (lVar n) x s = (if n < x then (lVar n) + else (if n = x then s else (lVar (n - 1))))" + | vsub_lApp: "vsub (lApp t u) x s = (lApp (vsub t x s) (vsub u x s))" + | vsub_lLam: "vsub (lLam t) x s = (lLam (vsub t (x + 1) s))" +using llam_cases +apply(auto simp add: llam.inject) +apply(rotate_tac 4) +apply(drule_tac x="a" in meta_spec) +apply(blast) +done + +termination vsub +proof + show "wf (measure (llam_size \ fst))" by simp +qed (auto) + +lemma vsub_eqvt[eqvt]: + fixes pi::"name prm" + shows "pi\(vsub t n s) = vsub (pi\t) (pi\n) (pi\s)" +by (induct t arbitrary: n rule: llam.weak_induct) + (simp_all add: perm_nat_def) + +constdefs + freshen :: "llam \ name \ llam" + "freshen t p \ vsub t 0 (lPar p)" + +lemma freshen_eqvt[eqvt]: + fixes pi::"name prm" + shows "pi\(freshen t p) = freshen (pi\t) (pi\p)" +by (simp add: vsub_eqvt freshen_def perm_nat_def) + +nominal_datatype ty = + TVar "nat" + | TArr "ty" "ty" (infix "\" 200) + +lemma ty_perm[simp]: + fixes pi ::"name prm" + and T ::"ty" + shows "pi\T = T" +by (induct T rule: ty.weak_induct) + (simp_all add: perm_nat_def) + +lemma ty_fresh[simp]: + fixes x::"name" + and T::"ty" + shows "x\T" +by (induct T rule: ty.weak_induct) + (simp_all add: fresh_nat) + +text {* valid contexts *} +types cxt = "(name\ty) list" + +inductive2 + valid :: "cxt \ bool" +where + v1[intro]: "valid []" +| v2[intro]: "\valid \;a\\\\ valid ((a,T)#\)" + +equivariance valid + +lemma v2_elim: + assumes a: "valid ((a,T)#\)" + shows "a\\ \ valid \" +using valid.cases[OF a] +by (auto) + +inductive2 + typing :: "cxt\llam\ty\bool" (" _ \ _ : _ " [80,80,80] 80) +where + t_lPar[intro]: "\valid \; (a,T)\set \\\ \ \ lPar a : T" + | t_lApp[intro]: "\\ \ t1 : T1\T2; \ \ t2 : T1\\ \ \ lApp t1 t2 : T2" + | t_lLam[intro]: "\a\t; ((a,T1)#\) \ (freshen t a) : T2\\ \ \ lLam t : T1\T2" + +equivariance typing + +lemma typing_implies_valid: + assumes a: "\ \ t : T" + shows "valid \" +using a +by (induct) (auto dest: v2_elim) + +nominal_inductive typing + avoids t_lLam: a + by (auto simp add: fresh_prod dest: v2_elim typing_implies_valid) + +(* strong induction principle for typing *) +thm typing.strong_induct + +abbreviation + "sub_context" :: "cxt \ cxt \ bool" ("_ \ _" [60,60] 60) +where + "\1 \ \2 \ \x T. (x,T)\set \1 \ (x,T)\set \2" + +lemma weakening_automatic: + assumes a: "\1 \ t : T" + and b: "\1 \ \2" + and c: "valid \2" +shows "\2 \ t : T" +using a b c +apply(nominal_induct \1 t T avoiding: \2 rule: typing.strong_induct) +apply(auto)[1] +apply(auto)[1] +apply(drule_tac x="(a,T1)#\2" in meta_spec) +apply(auto intro!: t_lLam) +done + +lemma weakening: + assumes a: "\1 \ t : T" + and b: "\1 \ \2" + and c: "valid \2" +shows "\2 \ t : T" +using a b c +proof(nominal_induct \1 t T avoiding: \2 rule: typing.strong_induct) + case (t_lPar \1 x T \2) (* variable case *) + have "\1 \ \2" by fact + moreover + have "valid \2" by fact + moreover + have "(x,T)\ set \1" by fact + ultimately show "\2 \ lPar x : T" by auto +next + case (t_lLam x t T1 \1 T2 \2) (* lambda case *) + have vc: "x\\2" "x\t" by fact (* variable convention *) + have ih: "\(x,T1)#\1 \ (x,T1)#\2; valid ((x,T1)#\2)\ \ ((x,T1)#\2) \ freshen t x : T2" by fact + have "\1 \ \2" by fact + then have "(x,T1)#\1 \ (x,T1)#\2" by simp + moreover + have "valid \2" by fact + then have "valid ((x,T1)#\2)" using vc by (simp add: v2) + ultimately have "((x,T1)#\2) \ freshen t x : T2" using ih by simp + with vc show "\2 \ lLam t : T1\T2" by (auto simp add: fresh_prod) +qed (auto) (* app case *) + +end