Nominal/LamEx.thy
changeset 1258 7d8949da7d99
parent 1139 c4001cda9da3
child 1544 c6849a634582
equal deleted inserted replaced
1252:4b0563bc4b03 1258:7d8949da7d99
       
     1 theory LamEx
       
     2 imports "Nominal2_Atoms" "Nominal2_Eqvt" "Nominal2_Supp" "Abs"
       
     3 begin
       
     4 
       
     5 atom_decl name
       
     6 
       
     7 datatype rlam =
       
     8   rVar "name"
       
     9 | rApp "rlam" "rlam"
       
    10 | rLam "name" "rlam"
       
    11 
       
    12 fun
       
    13   rfv :: "rlam \<Rightarrow> atom set"
       
    14 where
       
    15   rfv_var: "rfv (rVar a) = {atom a}"
       
    16 | rfv_app: "rfv (rApp t1 t2) = (rfv t1) \<union> (rfv t2)"
       
    17 | rfv_lam: "rfv (rLam a t) = (rfv t) - {atom a}"
       
    18 
       
    19 instantiation rlam :: pt
       
    20 begin
       
    21 
       
    22 primrec
       
    23   permute_rlam
       
    24 where
       
    25   "permute_rlam pi (rVar a) = rVar (pi \<bullet> a)"
       
    26 | "permute_rlam pi (rApp t1 t2) = rApp (permute_rlam pi t1) (permute_rlam pi t2)"
       
    27 | "permute_rlam pi (rLam a t) = rLam (pi \<bullet> a) (permute_rlam pi t)"
       
    28 
       
    29 instance
       
    30 apply default
       
    31 apply(induct_tac [!] x)
       
    32 apply(simp_all)
       
    33 done
       
    34 
       
    35 end
       
    36 
       
    37 instantiation rlam :: fs
       
    38 begin
       
    39 
       
    40 lemma neg_conj:
       
    41   "\<not>(P \<and> Q) \<longleftrightarrow> (\<not>P) \<or> (\<not>Q)"
       
    42   by simp
       
    43 
       
    44 lemma infinite_Un:
       
    45   "infinite (S \<union> T) \<longleftrightarrow> infinite S \<or> infinite T"
       
    46   by simp
       
    47 
       
    48 instance
       
    49 apply default
       
    50 apply(induct_tac x)
       
    51 (* var case *)
       
    52 apply(simp add: supp_def)
       
    53 apply(fold supp_def)[1]
       
    54 apply(simp add: supp_at_base)
       
    55 (* app case *)
       
    56 apply(simp only: supp_def)
       
    57 apply(simp only: permute_rlam.simps) 
       
    58 apply(simp only: rlam.inject) 
       
    59 apply(simp only: neg_conj)
       
    60 apply(simp only: Collect_disj_eq)
       
    61 apply(simp only: infinite_Un)
       
    62 apply(simp only: Collect_disj_eq)
       
    63 apply(simp)
       
    64 (* lam case *)
       
    65 apply(simp only: supp_def)
       
    66 apply(simp only: permute_rlam.simps) 
       
    67 apply(simp only: rlam.inject) 
       
    68 apply(simp only: neg_conj)
       
    69 apply(simp only: Collect_disj_eq)
       
    70 apply(simp only: infinite_Un)
       
    71 apply(simp only: Collect_disj_eq)
       
    72 apply(simp)
       
    73 apply(fold supp_def)[1]
       
    74 apply(simp add: supp_at_base)
       
    75 done
       
    76 
       
    77 end
       
    78 
       
    79 
       
    80 (* for the eqvt proof of the alpha-equivalence *)
       
    81 declare permute_rlam.simps[eqvt]
       
    82 
       
    83 lemma rfv_eqvt[eqvt]:
       
    84   shows "(pi\<bullet>rfv t) = rfv (pi\<bullet>t)"
       
    85 apply(induct t)
       
    86 apply(simp_all)
       
    87 apply(simp add: permute_set_eq atom_eqvt)
       
    88 apply(simp add: union_eqvt)
       
    89 apply(simp add: Diff_eqvt)
       
    90 apply(simp add: permute_set_eq atom_eqvt)
       
    91 done
       
    92 
       
    93 inductive
       
    94     alpha :: "rlam \<Rightarrow> rlam \<Rightarrow> bool" ("_ \<approx> _" [100, 100] 100)
       
    95 where
       
    96   a1: "a = b \<Longrightarrow> (rVar a) \<approx> (rVar b)"
       
    97 | a2: "\<lbrakk>t1 \<approx> t2; s1 \<approx> s2\<rbrakk> \<Longrightarrow> rApp t1 s1 \<approx> rApp t2 s2"
       
    98 | a3: "\<exists>pi. (rfv t - {atom a} = rfv s - {atom b} \<and> (rfv t - {atom a})\<sharp>* pi \<and> (pi \<bullet> t) \<approx> s)
       
    99        \<Longrightarrow> rLam a t \<approx> rLam b s"
       
   100 
       
   101 lemma a3_inverse:
       
   102   assumes "rLam a t \<approx> rLam b s"
       
   103   shows "\<exists>pi. (rfv t - {atom a} = rfv s - {atom b} \<and> (rfv t - {atom a})\<sharp>* pi \<and> (pi \<bullet> t) \<approx> s)"
       
   104 using assms
       
   105 apply(erule_tac alpha.cases)
       
   106 apply(auto)
       
   107 done
       
   108 
       
   109 text {* should be automatic with new version of eqvt-machinery *}
       
   110 lemma alpha_eqvt:
       
   111   shows "t \<approx> s \<Longrightarrow> (pi \<bullet> t) \<approx> (pi \<bullet> s)"
       
   112 apply(induct rule: alpha.induct)
       
   113 apply(simp add: a1)
       
   114 apply(simp add: a2)
       
   115 apply(simp)
       
   116 apply(rule a3)
       
   117 apply(erule conjE)
       
   118 apply(erule exE)
       
   119 apply(erule conjE)
       
   120 apply(rule_tac x="pi \<bullet> pia" in exI)
       
   121 apply(rule conjI)
       
   122 apply(rule_tac ?p1="- pi" in permute_eq_iff[THEN iffD1])
       
   123 apply(simp only: Diff_eqvt rfv_eqvt insert_eqvt atom_eqvt empty_eqvt)
       
   124 apply(simp)
       
   125 apply(rule conjI)
       
   126 apply(rule_tac ?p1="- pi" in fresh_star_permute_iff[THEN iffD1])
       
   127 apply(simp add: Diff_eqvt rfv_eqvt atom_eqvt insert_eqvt empty_eqvt)
       
   128 apply(subst permute_eqvt[symmetric])
       
   129 apply(simp)
       
   130 done
       
   131 
       
   132 lemma alpha_refl:
       
   133   shows "t \<approx> t"
       
   134 apply(induct t rule: rlam.induct)
       
   135 apply(simp add: a1)
       
   136 apply(simp add: a2)
       
   137 apply(rule a3)
       
   138 apply(rule_tac x="0" in exI)
       
   139 apply(simp_all add: fresh_star_def fresh_zero_perm)
       
   140 done
       
   141 
       
   142 lemma alpha_sym:
       
   143   shows "t \<approx> s \<Longrightarrow> s \<approx> t"
       
   144 apply(induct rule: alpha.induct)
       
   145 apply(simp add: a1)
       
   146 apply(simp add: a2)
       
   147 apply(rule a3)
       
   148 apply(erule exE)
       
   149 apply(rule_tac x="- pi" in exI)
       
   150 apply(simp)
       
   151 apply(simp add: fresh_star_def fresh_minus_perm)
       
   152 apply(erule conjE)+
       
   153 apply(rotate_tac 3)
       
   154 apply(drule_tac pi="- pi" in alpha_eqvt)
       
   155 apply(simp)
       
   156 done
       
   157 
       
   158 lemma alpha_trans:
       
   159   shows "t1 \<approx> t2 \<Longrightarrow> t2 \<approx> t3 \<Longrightarrow> t1 \<approx> t3"
       
   160 apply(induct arbitrary: t3 rule: alpha.induct)
       
   161 apply(erule alpha.cases)
       
   162 apply(simp_all)
       
   163 apply(simp add: a1)
       
   164 apply(rotate_tac 4)
       
   165 apply(erule alpha.cases)
       
   166 apply(simp_all)
       
   167 apply(simp add: a2)
       
   168 apply(rotate_tac 1)
       
   169 apply(erule alpha.cases)
       
   170 apply(simp_all)
       
   171 apply(erule conjE)+
       
   172 apply(erule exE)+
       
   173 apply(erule conjE)+
       
   174 apply(rule a3)
       
   175 apply(rule_tac x="pia + pi" in exI)
       
   176 apply(simp add: fresh_star_plus)
       
   177 apply(drule_tac x="- pia \<bullet> sa" in spec)
       
   178 apply(drule mp)
       
   179 apply(rotate_tac 7)
       
   180 apply(drule_tac pi="- pia" in alpha_eqvt)
       
   181 apply(simp)
       
   182 apply(rotate_tac 9)
       
   183 apply(drule_tac pi="pia" in alpha_eqvt)
       
   184 apply(simp)
       
   185 done
       
   186 
       
   187 lemma alpha_equivp:
       
   188   shows "equivp alpha"
       
   189   apply(rule equivpI)
       
   190   unfolding reflp_def symp_def transp_def
       
   191   apply(auto intro: alpha_refl alpha_sym alpha_trans)
       
   192   done
       
   193 
       
   194 lemma alpha_rfv:
       
   195   shows "t \<approx> s \<Longrightarrow> rfv t = rfv s"
       
   196   apply(induct rule: alpha.induct)
       
   197   apply(simp_all)
       
   198   done
       
   199 
       
   200 inductive
       
   201     alpha2 :: "rlam \<Rightarrow> rlam \<Rightarrow> bool" ("_ \<approx>2 _" [100, 100] 100)
       
   202 where
       
   203   a21: "a = b \<Longrightarrow> (rVar a) \<approx>2 (rVar b)"
       
   204 | a22: "\<lbrakk>t1 \<approx>2 t2; s1 \<approx>2 s2\<rbrakk> \<Longrightarrow> rApp t1 s1 \<approx>2 rApp t2 s2"
       
   205 | a23: "(a = b \<and> t \<approx>2 s) \<or> (a \<noteq> b \<and> ((a \<leftrightarrow> b) \<bullet> t) \<approx>2 s \<and> atom b \<notin> rfv t)\<Longrightarrow> rLam a t \<approx>2 rLam b s"
       
   206 
       
   207 lemma fv_vars:
       
   208   fixes a::name
       
   209   assumes a1: "\<forall>x \<in> rfv t - {atom a}. pi \<bullet> x = x"
       
   210   shows "(pi \<bullet> t) \<approx>2 ((a \<leftrightarrow> (pi \<bullet> a)) \<bullet> t)"
       
   211 using a1
       
   212 apply(induct t)
       
   213 apply(auto)
       
   214 apply(rule a21)
       
   215 apply(case_tac "name = a")
       
   216 apply(simp)
       
   217 apply(simp)
       
   218 defer
       
   219 apply(rule a22)
       
   220 apply(simp)
       
   221 apply(simp)
       
   222 apply(rule a23)
       
   223 apply(case_tac "a = name")
       
   224 apply(simp)
       
   225 oops
       
   226 
       
   227 
       
   228 lemma 
       
   229   assumes a1: "t \<approx>2 s"
       
   230   shows "t \<approx> s"
       
   231 using a1
       
   232 apply(induct)
       
   233 apply(rule alpha.intros)
       
   234 apply(simp)
       
   235 apply(rule alpha.intros)
       
   236 apply(simp)
       
   237 apply(simp)
       
   238 apply(rule alpha.intros)
       
   239 apply(erule disjE)
       
   240 apply(rule_tac x="0" in exI)
       
   241 apply(simp add: fresh_star_def fresh_zero_perm)
       
   242 apply(erule conjE)+
       
   243 apply(drule alpha_rfv)
       
   244 apply(simp)
       
   245 apply(rule_tac x="(a \<leftrightarrow> b)" in exI)
       
   246 apply(simp)
       
   247 apply(erule conjE)+
       
   248 apply(rule conjI)
       
   249 apply(drule alpha_rfv)
       
   250 apply(drule sym)
       
   251 apply(simp)
       
   252 apply(simp add: rfv_eqvt[symmetric])
       
   253 defer
       
   254 apply(subgoal_tac "atom a \<sharp> (rfv t - {atom a})")
       
   255 apply(subgoal_tac "atom b \<sharp> (rfv t - {atom a})")
       
   256 
       
   257 defer
       
   258 sorry
       
   259 
       
   260 lemma 
       
   261   assumes a1: "t \<approx> s"
       
   262   shows "t \<approx>2 s"
       
   263 using a1
       
   264 apply(induct)
       
   265 apply(rule alpha2.intros)
       
   266 apply(simp)
       
   267 apply(rule alpha2.intros)
       
   268 apply(simp)
       
   269 apply(simp)
       
   270 apply(clarify)
       
   271 apply(rule alpha2.intros)
       
   272 apply(frule alpha_rfv)
       
   273 apply(rotate_tac 4)
       
   274 apply(drule sym)
       
   275 apply(simp)
       
   276 apply(drule sym)
       
   277 apply(simp)
       
   278 oops
       
   279 
       
   280 quotient_type lam = rlam / alpha
       
   281   by (rule alpha_equivp)
       
   282 
       
   283 quotient_definition
       
   284   "Var :: name \<Rightarrow> lam"
       
   285 is
       
   286   "rVar"
       
   287 
       
   288 quotient_definition
       
   289    "App :: lam \<Rightarrow> lam \<Rightarrow> lam"
       
   290 is
       
   291   "rApp"
       
   292 
       
   293 quotient_definition
       
   294   "Lam :: name \<Rightarrow> lam \<Rightarrow> lam"
       
   295 is
       
   296   "rLam"
       
   297 
       
   298 quotient_definition
       
   299   "fv :: lam \<Rightarrow> atom set"
       
   300 is
       
   301   "rfv"
       
   302 
       
   303 lemma perm_rsp[quot_respect]:
       
   304   "(op = ===> alpha ===> alpha) permute permute"
       
   305   apply(auto)
       
   306   apply(rule alpha_eqvt)
       
   307   apply(simp)
       
   308   done
       
   309 
       
   310 lemma rVar_rsp[quot_respect]:
       
   311   "(op = ===> alpha) rVar rVar"
       
   312   by (auto intro: a1)
       
   313 
       
   314 lemma rApp_rsp[quot_respect]: 
       
   315   "(alpha ===> alpha ===> alpha) rApp rApp"
       
   316   by (auto intro: a2)
       
   317 
       
   318 lemma rLam_rsp[quot_respect]: 
       
   319   "(op = ===> alpha ===> alpha) rLam rLam"
       
   320   apply(auto)
       
   321   apply(rule a3)
       
   322   apply(rule_tac x="0" in exI)
       
   323   unfolding fresh_star_def 
       
   324   apply(simp add: fresh_star_def fresh_zero_perm)
       
   325   apply(simp add: alpha_rfv)
       
   326   done
       
   327 
       
   328 lemma rfv_rsp[quot_respect]: 
       
   329   "(alpha ===> op =) rfv rfv"
       
   330 apply(simp add: alpha_rfv)
       
   331 done
       
   332 
       
   333 
       
   334 section {* lifted theorems *}
       
   335 
       
   336 lemma lam_induct:
       
   337   "\<lbrakk>\<And>name. P (Var name);
       
   338     \<And>lam1 lam2. \<lbrakk>P lam1; P lam2\<rbrakk> \<Longrightarrow> P (App lam1 lam2);
       
   339     \<And>name lam. P lam \<Longrightarrow> P (Lam name lam)\<rbrakk> 
       
   340     \<Longrightarrow> P lam"
       
   341   apply (lifting rlam.induct)
       
   342   done
       
   343 
       
   344 instantiation lam :: pt
       
   345 begin
       
   346 
       
   347 quotient_definition
       
   348   "permute_lam :: perm \<Rightarrow> lam \<Rightarrow> lam"
       
   349 is
       
   350   "permute :: perm \<Rightarrow> rlam \<Rightarrow> rlam"
       
   351 
       
   352 lemma permute_lam [simp]:
       
   353   shows "pi \<bullet> Var a = Var (pi \<bullet> a)"
       
   354   and   "pi \<bullet> App t1 t2 = App (pi \<bullet> t1) (pi \<bullet> t2)"
       
   355   and   "pi \<bullet> Lam a t = Lam (pi \<bullet> a) (pi \<bullet> t)"
       
   356 apply(lifting permute_rlam.simps)
       
   357 done
       
   358 
       
   359 instance
       
   360 apply default
       
   361 apply(induct_tac [!] x rule: lam_induct)
       
   362 apply(simp_all)
       
   363 done
       
   364 
       
   365 end
       
   366 
       
   367 lemma fv_lam [simp]: 
       
   368   shows "fv (Var a) = {atom a}"
       
   369   and   "fv (App t1 t2) = fv t1 \<union> fv t2"
       
   370   and   "fv (Lam a t) = fv t - {atom a}"
       
   371 apply(lifting rfv_var rfv_app rfv_lam)
       
   372 done
       
   373 
       
   374 lemma fv_eqvt:
       
   375   shows "(p \<bullet> fv t) = fv (p \<bullet> t)"
       
   376 apply(lifting rfv_eqvt)
       
   377 done
       
   378 
       
   379 lemma a1: 
       
   380   "a = b \<Longrightarrow> Var a = Var b"
       
   381   by  (lifting a1)
       
   382 
       
   383 lemma a2: 
       
   384   "\<lbrakk>x = xa; xb = xc\<rbrakk> \<Longrightarrow> App x xb = App xa xc"
       
   385   by  (lifting a2)
       
   386 
       
   387 lemma a3: 
       
   388   "\<lbrakk>\<exists>pi. (fv t - {atom a} = fv s - {atom b} \<and> (fv t - {atom a})\<sharp>* pi \<and> (pi \<bullet> t) = s)\<rbrakk> 
       
   389    \<Longrightarrow> Lam a t = Lam b s"
       
   390   apply  (lifting a3)
       
   391   done
       
   392 
       
   393 lemma a3_inv:
       
   394   assumes "Lam a t = Lam b s"
       
   395   shows "\<exists>pi. (fv t - {atom a} = fv s - {atom b} \<and> (fv t - {atom a})\<sharp>* pi \<and> (pi \<bullet> t) = s)"
       
   396 using assms
       
   397 apply(lifting a3_inverse)
       
   398 done
       
   399 
       
   400 lemma alpha_cases: 
       
   401   "\<lbrakk>a1 = a2; \<And>a b. \<lbrakk>a1 = Var a; a2 = Var b; a = b\<rbrakk> \<Longrightarrow> P;
       
   402     \<And>x xa xb xc. \<lbrakk>a1 = App x xb; a2 = App xa xc; x = xa; xb = xc\<rbrakk> \<Longrightarrow> P;
       
   403     \<And>t a s b. \<lbrakk>a1 = Lam a t; a2 = Lam b s; 
       
   404          \<exists>pi. fv t - {atom a} = fv s - {atom b} \<and> (fv t - {atom a}) \<sharp>* pi \<and> (pi \<bullet> t) = s\<rbrakk> 
       
   405    \<Longrightarrow> P\<rbrakk>
       
   406     \<Longrightarrow> P"
       
   407   by (lifting alpha.cases)
       
   408 
       
   409 (* not sure whether needed *)
       
   410 lemma alpha_induct: 
       
   411   "\<lbrakk>qx = qxa; \<And>a b. a = b \<Longrightarrow> qxb (Var a) (Var b);
       
   412     \<And>x xa xb xc. \<lbrakk>x = xa; qxb x xa; xb = xc; qxb xb xc\<rbrakk> \<Longrightarrow> qxb (App x xb) (App xa xc);
       
   413      \<And>t a s b.
       
   414         \<lbrakk>\<exists>pi. fv t - {atom a} = fv s - {atom b} \<and>
       
   415          (fv t - {atom a}) \<sharp>* pi \<and> ((pi \<bullet> t) = s \<and> qxb (pi \<bullet> t) s)\<rbrakk> 
       
   416      \<Longrightarrow> qxb (Lam a t) (Lam b s)\<rbrakk>
       
   417     \<Longrightarrow> qxb qx qxa"
       
   418   by (lifting alpha.induct)
       
   419 
       
   420 (* should they lift automatically *)
       
   421 lemma lam_inject [simp]: 
       
   422   shows "(Var a = Var b) = (a = b)"
       
   423   and   "(App t1 t2 = App s1 s2) = (t1 = s1 \<and> t2 = s2)"
       
   424 apply(lifting rlam.inject(1) rlam.inject(2))
       
   425 apply(regularize)
       
   426 prefer 2
       
   427 apply(regularize)
       
   428 prefer 2
       
   429 apply(auto)
       
   430 apply(drule alpha.cases)
       
   431 apply(simp_all)
       
   432 apply(simp add: alpha.a1)
       
   433 apply(drule alpha.cases)
       
   434 apply(simp_all)
       
   435 apply(drule alpha.cases)
       
   436 apply(simp_all)
       
   437 apply(rule alpha.a2)
       
   438 apply(simp_all)
       
   439 done
       
   440 
       
   441 lemma Lam_pseudo_inject:
       
   442   shows "(Lam a t = Lam b s) = 
       
   443       (\<exists>pi. (fv t - {atom a} = fv s - {atom b} \<and> (fv t - {atom a})\<sharp>* pi \<and> (pi \<bullet> t) = s))"
       
   444 apply(rule iffI)
       
   445 apply(rule a3_inv)
       
   446 apply(assumption)
       
   447 apply(rule a3)
       
   448 apply(assumption)
       
   449 done
       
   450 
       
   451 lemma rlam_distinct:
       
   452   shows "\<not>(rVar nam \<approx> rApp rlam1' rlam2')"
       
   453   and   "\<not>(rApp rlam1' rlam2' \<approx> rVar nam)"
       
   454   and   "\<not>(rVar nam \<approx> rLam nam' rlam')"
       
   455   and   "\<not>(rLam nam' rlam' \<approx> rVar nam)"
       
   456   and   "\<not>(rApp rlam1 rlam2 \<approx> rLam nam' rlam')"
       
   457   and   "\<not>(rLam nam' rlam' \<approx> rApp rlam1 rlam2)"
       
   458 apply auto
       
   459 apply (erule alpha.cases)
       
   460 apply (simp_all only: rlam.distinct)
       
   461 apply (erule alpha.cases)
       
   462 apply (simp_all only: rlam.distinct)
       
   463 apply (erule alpha.cases)
       
   464 apply (simp_all only: rlam.distinct)
       
   465 apply (erule alpha.cases)
       
   466 apply (simp_all only: rlam.distinct)
       
   467 apply (erule alpha.cases)
       
   468 apply (simp_all only: rlam.distinct)
       
   469 apply (erule alpha.cases)
       
   470 apply (simp_all only: rlam.distinct)
       
   471 done
       
   472 
       
   473 lemma lam_distinct[simp]:
       
   474   shows "Var nam \<noteq> App lam1' lam2'"
       
   475   and   "App lam1' lam2' \<noteq> Var nam"
       
   476   and   "Var nam \<noteq> Lam nam' lam'"
       
   477   and   "Lam nam' lam' \<noteq> Var nam"
       
   478   and   "App lam1 lam2 \<noteq> Lam nam' lam'"
       
   479   and   "Lam nam' lam' \<noteq> App lam1 lam2"
       
   480 apply(lifting rlam_distinct(1) rlam_distinct(2) rlam_distinct(3) rlam_distinct(4) rlam_distinct(5) rlam_distinct(6))
       
   481 done
       
   482 
       
   483 lemma var_supp1:
       
   484   shows "(supp (Var a)) = (supp a)"
       
   485   apply (simp add: supp_def)
       
   486   done
       
   487 
       
   488 lemma var_supp:
       
   489   shows "(supp (Var a)) = {a:::name}"
       
   490   using var_supp1 by (simp add: supp_at_base)
       
   491 
       
   492 lemma app_supp:
       
   493   shows "supp (App t1 t2) = (supp t1) \<union> (supp t2)"
       
   494 apply(simp only: supp_def lam_inject)
       
   495 apply(simp add: Collect_imp_eq Collect_neg_eq)
       
   496 done
       
   497 
       
   498 (* supp for lam *)
       
   499 lemma lam_supp1:
       
   500   shows "(supp (atom x, t)) supports (Lam x t) "
       
   501 apply(simp add: supports_def)
       
   502 apply(fold fresh_def)
       
   503 apply(simp add: fresh_Pair swap_fresh_fresh)
       
   504 apply(clarify)
       
   505 apply(subst swap_at_base_simps(3))
       
   506 apply(simp_all add: fresh_atom)
       
   507 done
       
   508 
       
   509 lemma lam_fsupp1:
       
   510   assumes a: "finite (supp t)"
       
   511   shows "finite (supp (Lam x t))"
       
   512 apply(rule supports_finite)
       
   513 apply(rule lam_supp1)
       
   514 apply(simp add: a supp_Pair supp_atom)
       
   515 done
       
   516 
       
   517 instance lam :: fs
       
   518 apply(default)
       
   519 apply(induct_tac x rule: lam_induct)
       
   520 apply(simp add: var_supp)
       
   521 apply(simp add: app_supp)
       
   522 apply(simp add: lam_fsupp1)
       
   523 done
       
   524 
       
   525 lemma supp_fv:
       
   526   shows "supp t = fv t"
       
   527 apply(induct t rule: lam_induct)
       
   528 apply(simp add: var_supp)
       
   529 apply(simp add: app_supp)
       
   530 apply(subgoal_tac "supp (Lam name lam) = supp (Abs {atom name} lam)")
       
   531 apply(simp add: supp_Abs)
       
   532 apply(simp (no_asm) add: supp_def permute_set_eq atom_eqvt)
       
   533 apply(simp add: Lam_pseudo_inject)
       
   534 apply(simp add: Abs_eq_iff alpha_gen)
       
   535 apply(simp add: supp_eqvt[symmetric] fv_eqvt[symmetric])
       
   536 done
       
   537 
       
   538 lemma lam_supp2:
       
   539   shows "supp (Lam x t) = supp (Abs {atom x} t)"
       
   540 apply(simp add: supp_def permute_set_eq atom_eqvt)
       
   541 apply(simp add: Lam_pseudo_inject)
       
   542 apply(simp add: Abs_eq_iff supp_fv alpha_gen)
       
   543 done
       
   544 
       
   545 lemma lam_supp:
       
   546   shows "supp (Lam x t) = ((supp t) - {atom x})"
       
   547 apply(simp add: lam_supp2)
       
   548 apply(simp add: supp_Abs)
       
   549 done
       
   550 
       
   551 lemma fresh_lam:
       
   552   "(atom a \<sharp> Lam b t) \<longleftrightarrow> (a = b) \<or> (a \<noteq> b \<and> atom a \<sharp> t)"
       
   553 apply(simp add: fresh_def)
       
   554 apply(simp add: lam_supp)
       
   555 apply(auto)
       
   556 done
       
   557 
       
   558 lemma lam_induct_strong:
       
   559   fixes a::"'a::fs"
       
   560   assumes a1: "\<And>name b. P b (Var name)"
       
   561   and     a2: "\<And>lam1 lam2 b. \<lbrakk>\<And>c. P c lam1; \<And>c. P c lam2\<rbrakk> \<Longrightarrow> P b (App lam1 lam2)"
       
   562   and     a3: "\<And>name lam b. \<lbrakk>\<And>c. P c lam; (atom name) \<sharp> b\<rbrakk> \<Longrightarrow> P b (Lam name lam)"
       
   563   shows "P a lam"
       
   564 proof -
       
   565   have "\<And>pi a. P a (pi \<bullet> lam)" 
       
   566   proof (induct lam rule: lam_induct)
       
   567     case (1 name pi)
       
   568     show "P a (pi \<bullet> Var name)"
       
   569       apply (simp)
       
   570       apply (rule a1)
       
   571       done
       
   572   next
       
   573     case (2 lam1 lam2 pi)
       
   574     have b1: "\<And>pi a. P a (pi \<bullet> lam1)" by fact
       
   575     have b2: "\<And>pi a. P a (pi \<bullet> lam2)" by fact
       
   576     show "P a (pi \<bullet> App lam1 lam2)"
       
   577       apply (simp)
       
   578       apply (rule a2)
       
   579       apply (rule b1)
       
   580       apply (rule b2)
       
   581       done
       
   582   next
       
   583     case (3 name lam pi a)
       
   584     have b: "\<And>pi a. P a (pi \<bullet> lam)" by fact
       
   585     obtain c::name where fr: "atom c\<sharp>(a, pi\<bullet>name, pi\<bullet>lam)"
       
   586       apply(rule obtain_atom)
       
   587       apply(auto)
       
   588       sorry
       
   589     from b fr have p: "P a (Lam c (((c \<leftrightarrow> (pi \<bullet> name)) + pi)\<bullet>lam))" 
       
   590       apply -
       
   591       apply(rule a3)
       
   592       apply(blast)
       
   593       apply(simp add: fresh_Pair)
       
   594       done
       
   595     have eq: "(atom c \<rightleftharpoons> atom (pi\<bullet>name)) \<bullet> Lam (pi \<bullet> name) (pi \<bullet> lam) = Lam (pi \<bullet> name) (pi \<bullet> lam)"
       
   596       apply(rule swap_fresh_fresh)
       
   597       using fr
       
   598       apply(simp add: fresh_lam fresh_Pair)
       
   599       apply(simp add: fresh_lam fresh_Pair)
       
   600       done
       
   601     show "P a (pi \<bullet> Lam name lam)" 
       
   602       apply (simp)
       
   603       apply(subst eq[symmetric])
       
   604       using p
       
   605       apply(simp only: permute_lam)
       
   606       apply(simp add: flip_def)
       
   607       done
       
   608   qed
       
   609   then have "P a (0 \<bullet> lam)" by blast
       
   610   then show "P a lam" by simp 
       
   611 qed
       
   612 
       
   613 
       
   614 lemma var_fresh:
       
   615   fixes a::"name"
       
   616   shows "(atom a \<sharp> (Var b)) = (atom a \<sharp> b)"
       
   617   apply(simp add: fresh_def)
       
   618   apply(simp add: var_supp1)
       
   619   done
       
   620 
       
   621 
       
   622 
       
   623 end
       
   624