Quot/Nominal/LamEx2.thy
changeset 1011 1dd314a00b0c
child 1017 4239a0784e5f
equal deleted inserted replaced
1010:6f2bbe35987a 1011:1dd314a00b0c
       
     1 theory LamEx
       
     2 imports Nominal "../QuotMain" "../QuotList"
       
     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> name set"
       
    14 where
       
    15   rfv_var: "rfv (rVar a) = {a}"
       
    16 | rfv_app: "rfv (rApp t1 t2) = (rfv t1) \<union> (rfv t2)"
       
    17 | rfv_lam: "rfv (rLam a t) = (rfv t) - {a}"
       
    18 
       
    19 overloading
       
    20   perm_rlam \<equiv> "perm :: 'x prm \<Rightarrow> rlam \<Rightarrow> rlam"   (unchecked)
       
    21 begin
       
    22 
       
    23 fun
       
    24   perm_rlam
       
    25 where
       
    26   "perm_rlam pi (rVar a) = rVar (pi \<bullet> a)"
       
    27 | "perm_rlam pi (rApp t1 t2) = rApp (perm_rlam pi t1) (perm_rlam pi t2)"
       
    28 | "perm_rlam pi (rLam a t) = rLam (pi \<bullet> a) (perm_rlam pi t)"
       
    29 
       
    30 end
       
    31 
       
    32 declare perm_rlam.simps[eqvt]
       
    33 
       
    34 instance rlam::pt_name
       
    35   apply(default)
       
    36   apply(induct_tac [!] x rule: rlam.induct)
       
    37   apply(simp_all add: pt_name2 pt_name3)
       
    38   done
       
    39 
       
    40 instance rlam::fs_name
       
    41   apply(default)
       
    42   apply(induct_tac [!] x rule: rlam.induct)
       
    43   apply(simp add: supp_def)
       
    44   apply(fold supp_def)
       
    45   apply(simp add: supp_atm)
       
    46   apply(simp add: supp_def Collect_imp_eq Collect_neg_eq)
       
    47   apply(simp add: supp_def)
       
    48   apply(simp add: supp_def Collect_imp_eq Collect_neg_eq[symmetric])
       
    49   apply(fold supp_def)
       
    50   apply(simp add: supp_atm)
       
    51   done
       
    52 
       
    53 declare set_diff_eqvt[eqvt]
       
    54 
       
    55 lemma rfv_eqvt[eqvt]:
       
    56   fixes pi::"name prm"
       
    57   shows "(pi\<bullet>rfv t) = rfv (pi\<bullet>t)"
       
    58 apply(induct t)
       
    59 apply(simp_all)
       
    60 apply(simp add: perm_set_eq)
       
    61 apply(simp add: union_eqvt)
       
    62 apply(simp add: set_diff_eqvt)
       
    63 apply(simp add: perm_set_eq)
       
    64 done
       
    65 
       
    66 inductive
       
    67     alpha :: "rlam \<Rightarrow> rlam \<Rightarrow> bool" ("_ \<approx> _" [100, 100] 100)
       
    68 where
       
    69   a1: "a = b \<Longrightarrow> (rVar a) \<approx> (rVar b)"
       
    70 | a2: "\<lbrakk>t1 \<approx> t2; s1 \<approx> s2\<rbrakk> \<Longrightarrow> rApp t1 s1 \<approx> rApp t2 s2"
       
    71 | a3: "\<exists>pi::name prm. (rfv t - {a} = rfv s - {b} \<and> (rfv t - {a})\<sharp>* pi \<and> (pi \<bullet> t) \<approx> s \<and> (pi \<bullet> a) = b)
       
    72        \<Longrightarrow> rLam a t \<approx> rLam b s"
       
    73 
       
    74 
       
    75 
       
    76 
       
    77 (* should be automatic with new version of eqvt-machinery *)
       
    78 lemma alpha_eqvt:
       
    79   fixes pi::"name prm"
       
    80   shows "t \<approx> s \<Longrightarrow> (pi \<bullet> t) \<approx> (pi \<bullet> s)"
       
    81 apply(induct rule: alpha.induct)
       
    82 apply(simp add: a1)
       
    83 apply(simp add: a2)
       
    84 apply(simp)
       
    85 apply(rule a3)
       
    86 apply(erule conjE)
       
    87 apply(erule exE)
       
    88 apply(erule conjE)
       
    89 apply(rule_tac x="pi \<bullet> pia" in exI)
       
    90 apply(rule conjI)
       
    91 apply(rule_tac pi1="rev pi" in perm_bij[THEN iffD1])
       
    92 apply(perm_simp add: eqvts)
       
    93 apply(rule conjI)
       
    94 apply(rule_tac pi1="rev pi" in pt_fresh_star_bij(1)[OF pt_name_inst at_name_inst, THEN iffD1])
       
    95 apply(perm_simp add: eqvts)
       
    96 apply(rule conjI)
       
    97 apply(subst perm_compose[symmetric])
       
    98 apply(simp)
       
    99 apply(subst perm_compose[symmetric])
       
   100 apply(simp)
       
   101 done
       
   102 
       
   103 lemma alpha_refl:
       
   104   shows "t \<approx> t"
       
   105 apply(induct t rule: rlam.induct)
       
   106 apply(simp add: a1)
       
   107 apply(simp add: a2)
       
   108 apply(rule a3)
       
   109 apply(rule_tac x="[]" in exI)
       
   110 apply(simp_all add: fresh_star_def fresh_list_nil)
       
   111 done
       
   112 
       
   113 lemma alpha_sym:
       
   114   shows "t \<approx> s \<Longrightarrow> s \<approx> t"
       
   115 apply(induct rule: alpha.induct)
       
   116 apply(simp add: a1)
       
   117 apply(simp add: a2)
       
   118 apply(rule a3)
       
   119 apply(erule exE)
       
   120 apply(rule_tac x="rev pi" in exI)
       
   121 apply(simp)
       
   122 apply(simp add: fresh_star_def fresh_list_rev)
       
   123 apply(rule conjI)
       
   124 apply(erule conjE)+
       
   125 apply(rotate_tac 3)
       
   126 apply(drule_tac pi="rev pi" in alpha_eqvt)
       
   127 apply(perm_simp)
       
   128 apply(rule pt_bij2[OF pt_name_inst at_name_inst])
       
   129 apply(simp)
       
   130 done
       
   131 
       
   132 lemma alpha_trans:
       
   133   shows "t1 \<approx> t2 \<Longrightarrow> t2 \<approx> t3 \<Longrightarrow> t1 \<approx> t3"
       
   134 apply(induct arbitrary: t3 rule: alpha.induct)
       
   135 apply(erule alpha.cases)
       
   136 apply(simp_all)
       
   137 apply(simp add: a1)
       
   138 apply(rotate_tac 4)
       
   139 apply(erule alpha.cases)
       
   140 apply(simp_all)
       
   141 apply(simp add: a2)
       
   142 apply(rotate_tac 1)
       
   143 apply(erule alpha.cases)
       
   144 apply(simp_all)
       
   145 apply(erule conjE)+
       
   146 apply(erule exE)+
       
   147 apply(erule conjE)+
       
   148 apply(rule a3)
       
   149 apply(rule_tac x="pia @ pi" in exI)
       
   150 apply(simp add: fresh_star_def fresh_list_append)
       
   151 apply(simp add: pt_name2)
       
   152 apply(drule_tac x="rev pia \<bullet> sa" in spec)
       
   153 apply(drule mp)
       
   154 apply(rotate_tac 8)
       
   155 apply(drule_tac pi="rev pia" in alpha_eqvt)
       
   156 apply(perm_simp)
       
   157 apply(rotate_tac 11)
       
   158 apply(drule_tac pi="pia" in alpha_eqvt)
       
   159 apply(perm_simp)
       
   160 done
       
   161 
       
   162 lemma alpha_equivp:
       
   163   shows "equivp alpha"
       
   164 apply(rule equivpI)
       
   165 unfolding reflp_def symp_def transp_def
       
   166 apply(auto intro: alpha_refl alpha_sym alpha_trans)
       
   167 done
       
   168 
       
   169 lemma alpha_rfv:
       
   170   shows "t \<approx> s \<Longrightarrow> rfv t = rfv s"
       
   171 apply(induct rule: alpha.induct)
       
   172 apply(simp)
       
   173 apply(simp)
       
   174 apply(simp)
       
   175 done
       
   176 
       
   177 quotient_type lam = rlam / alpha
       
   178   by (rule alpha_equivp)
       
   179 
       
   180 
       
   181 quotient_definition
       
   182   "Var :: name \<Rightarrow> lam"
       
   183 as
       
   184   "rVar"
       
   185 
       
   186 quotient_definition
       
   187    "App :: lam \<Rightarrow> lam \<Rightarrow> lam"
       
   188 as
       
   189   "rApp"
       
   190 
       
   191 quotient_definition
       
   192   "Lam :: name \<Rightarrow> lam \<Rightarrow> lam"
       
   193 as
       
   194   "rLam"
       
   195 
       
   196 quotient_definition
       
   197   "fv :: lam \<Rightarrow> name set"
       
   198 as
       
   199   "rfv"
       
   200 
       
   201 (* definition of overloaded permutation function *)
       
   202 (* for the lifted type lam                       *)
       
   203 overloading
       
   204   perm_lam \<equiv> "perm :: 'x prm \<Rightarrow> lam \<Rightarrow> lam"   (unchecked)
       
   205 begin
       
   206 
       
   207 quotient_definition
       
   208   "perm_lam :: 'x prm \<Rightarrow> lam \<Rightarrow> lam"
       
   209 as
       
   210   "perm::'x prm \<Rightarrow> rlam \<Rightarrow> rlam"
       
   211 
       
   212 end
       
   213 
       
   214 lemma perm_rsp[quot_respect]:
       
   215   "(op = ===> alpha ===> alpha) op \<bullet> op \<bullet>"
       
   216   apply(auto)
       
   217   (* this is propably true if some type conditions are imposed ;o) *)
       
   218   sorry
       
   219 
       
   220 lemma fresh_rsp:
       
   221   "(op = ===> alpha ===> op =) fresh fresh"
       
   222   apply(auto)
       
   223   (* this is probably only true if some type conditions are imposed *)
       
   224   sorry
       
   225 
       
   226 lemma rVar_rsp[quot_respect]:
       
   227   "(op = ===> alpha) rVar rVar"
       
   228   by (auto intro: a1)
       
   229 
       
   230 lemma rApp_rsp[quot_respect]: "(alpha ===> alpha ===> alpha) rApp rApp"
       
   231   by (auto intro: a2)
       
   232 
       
   233 lemma rLam_rsp[quot_respect]: "(op = ===> alpha ===> alpha) rLam rLam"
       
   234   apply(auto)
       
   235   apply(rule a3)
       
   236   apply(rule_tac x="[]" in exI)
       
   237   unfolding fresh_star_def
       
   238   apply(simp add: fresh_list_nil)
       
   239   apply(simp add: alpha_rfv)
       
   240   done
       
   241 
       
   242 lemma rfv_rsp[quot_respect]: 
       
   243   "(alpha ===> op =) rfv rfv"
       
   244 apply(simp add: alpha_rfv)
       
   245 done
       
   246 
       
   247 section {* lifted theorems *}
       
   248 
       
   249 lemma lam_induct:
       
   250   "\<lbrakk>\<And>name. P (Var name);
       
   251     \<And>lam1 lam2. \<lbrakk>P lam1; P lam2\<rbrakk> \<Longrightarrow> P (App lam1 lam2);
       
   252     \<And>name lam. P lam \<Longrightarrow> P (Lam name lam)\<rbrakk> 
       
   253     \<Longrightarrow> P lam"
       
   254   by (lifting rlam.induct)
       
   255 
       
   256 lemma perm_lam [simp]:
       
   257   fixes pi::"'a prm"
       
   258   shows "pi \<bullet> Var a = Var (pi \<bullet> a)"
       
   259   and   "pi \<bullet> App t1 t2 = App (pi \<bullet> t1) (pi \<bullet> t2)"
       
   260   and   "pi \<bullet> Lam a t = Lam (pi \<bullet> a) (pi \<bullet> t)"
       
   261 apply(lifting perm_rlam.simps)
       
   262 done
       
   263 
       
   264 instance lam::pt_name
       
   265 apply(default)
       
   266 apply(induct_tac [!] x rule: lam_induct)
       
   267 apply(simp_all add: pt_name2 pt_name3)
       
   268 done
       
   269 
       
   270 lemma fv_lam [simp]: 
       
   271   shows "fv (Var a) = {a}"
       
   272   and   "fv (App t1 t2) = fv t1 \<union> fv t2"
       
   273   and   "fv (Lam a t) = fv t - {a}"
       
   274 apply(lifting rfv_var rfv_app rfv_lam)
       
   275 done
       
   276 
       
   277 
       
   278 lemma a1: 
       
   279   "a = b \<Longrightarrow> Var a = Var b"
       
   280   by  (lifting a1)
       
   281 
       
   282 lemma a2: 
       
   283   "\<lbrakk>x = xa; xb = xc\<rbrakk> \<Longrightarrow> App x xb = App xa xc"
       
   284   by  (lifting a2)
       
   285 
       
   286 lemma a3: 
       
   287   "\<lbrakk>\<exists>pi::name prm. (fv t - {a} = fv s - {b} \<and> (fv t - {a})\<sharp>* pi \<and> (pi \<bullet> t) = s \<and> (pi \<bullet> a) = b)\<rbrakk> 
       
   288    \<Longrightarrow> Lam a t = Lam b s"
       
   289   by  (lifting a3)
       
   290 
       
   291 lemma alpha_cases: 
       
   292   "\<lbrakk>a1 = a2; \<And>a b. \<lbrakk>a1 = Var a; a2 = Var b; a = b\<rbrakk> \<Longrightarrow> P;
       
   293     \<And>x xa xb xc. \<lbrakk>a1 = App x xb; a2 = App xa xc; x = xa; xb = xc\<rbrakk> \<Longrightarrow> P;
       
   294     \<And>t a s b. \<lbrakk>a1 = Lam a t; a2 = Lam b s; 
       
   295          \<exists>pi::name prm. fv t - {a} = fv s - {b} \<and> (fv t - {a}) \<sharp>* pi \<and> (pi \<bullet> t) = s \<and> pi \<bullet> a = b\<rbrakk> \<Longrightarrow> P\<rbrakk>
       
   296     \<Longrightarrow> P"
       
   297   by (lifting alpha.cases)
       
   298 
       
   299 lemma alpha_induct: 
       
   300   "\<lbrakk>qx = qxa; \<And>a b. a = b \<Longrightarrow> qxb (Var a) (Var b);
       
   301     \<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);
       
   302      \<And>t a s b.
       
   303         \<lbrakk>\<exists>pi::name prm. fv t - {a} = fv s - {b} \<and>
       
   304          (fv t - {a}) \<sharp>* pi \<and> ((pi \<bullet> t) = s \<and> qxb (pi \<bullet> t) s) \<and> pi \<bullet> a = b\<rbrakk> \<Longrightarrow> qxb (Lam a t) (Lam b s)\<rbrakk>
       
   305     \<Longrightarrow> qxb qx qxa"
       
   306   by (lifting alpha.induct)
       
   307 
       
   308 lemma lam_inject [simp]: 
       
   309   shows "(Var a = Var b) = (a = b)"
       
   310   and   "(App t1 t2 = App s1 s2) = (t1 = s1 \<and> t2 = s2)"
       
   311 apply(lifting rlam.inject(1) rlam.inject(2))
       
   312 apply(auto)
       
   313 apply(drule alpha.cases)
       
   314 apply(simp_all)
       
   315 apply(simp add: alpha.a1)
       
   316 apply(drule alpha.cases)
       
   317 apply(simp_all)
       
   318 apply(drule alpha.cases)
       
   319 apply(simp_all)
       
   320 apply(rule alpha.a2)
       
   321 apply(simp_all)
       
   322 done
       
   323 
       
   324 lemma rlam_distinct:
       
   325   shows "\<not>(rVar nam \<approx> rApp rlam1' rlam2')"
       
   326   and   "\<not>(rApp rlam1' rlam2' \<approx> rVar nam)"
       
   327   and   "\<not>(rVar nam \<approx> rLam nam' rlam')"
       
   328   and   "\<not>(rLam nam' rlam' \<approx> rVar nam)"
       
   329   and   "\<not>(rApp rlam1 rlam2 \<approx> rLam nam' rlam')"
       
   330   and   "\<not>(rLam nam' rlam' \<approx> rApp rlam1 rlam2)"
       
   331 apply auto
       
   332 apply(erule alpha.cases)
       
   333 apply simp_all
       
   334 apply(erule alpha.cases)
       
   335 apply simp_all
       
   336 apply(erule alpha.cases)
       
   337 apply simp_all
       
   338 apply(erule alpha.cases)
       
   339 apply simp_all
       
   340 apply(erule alpha.cases)
       
   341 apply simp_all
       
   342 apply(erule alpha.cases)
       
   343 apply simp_all
       
   344 done
       
   345 
       
   346 lemma lam_distinct[simp]:
       
   347   shows "Var nam \<noteq> App lam1' lam2'"
       
   348   and   "App lam1' lam2' \<noteq> Var nam"
       
   349   and   "Var nam \<noteq> Lam nam' lam'"
       
   350   and   "Lam nam' lam' \<noteq> Var nam"
       
   351   and   "App lam1 lam2 \<noteq> Lam nam' lam'"
       
   352   and   "Lam nam' lam' \<noteq> App lam1 lam2"
       
   353 apply(lifting rlam_distinct(1) rlam_distinct(2) rlam_distinct(3) rlam_distinct(4) rlam_distinct(5) rlam_distinct(6))
       
   354 done
       
   355 
       
   356 lemma var_supp1:
       
   357   shows "(supp (Var a)) = ((supp a)::name set)"
       
   358   by (simp add: supp_def)
       
   359 
       
   360 lemma var_supp:
       
   361   shows "(supp (Var a)) = {a::name}"
       
   362   using var_supp1 by (simp add: supp_atm)
       
   363 
       
   364 lemma app_supp:
       
   365   shows "supp (App t1 t2) = (supp t1) \<union> ((supp t2)::name set)"
       
   366 apply(simp only: perm_lam supp_def lam_inject)
       
   367 apply(simp add: Collect_imp_eq Collect_neg_eq)
       
   368 done
       
   369 
       
   370 lemma lam_supp:
       
   371   shows "supp (Lam x t) = ((supp ([x].t))::name set)"
       
   372 apply(simp add: supp_def)
       
   373 apply(simp add: abs_perm)
       
   374 sorry
       
   375 
       
   376 
       
   377 instance lam::fs_name
       
   378 apply(default)
       
   379 apply(induct_tac x rule: lam_induct)
       
   380 apply(simp add: var_supp)
       
   381 apply(simp add: app_supp)
       
   382 apply(simp add: lam_supp abs_supp)
       
   383 done
       
   384 
       
   385 lemma fresh_lam:
       
   386   "(a \<sharp> Lam b t) \<longleftrightarrow> (a = b) \<or> (a \<noteq> b \<and> a \<sharp> t)"
       
   387 apply(simp add: fresh_def)
       
   388 apply(simp add: lam_supp abs_supp)
       
   389 apply(auto)
       
   390 done
       
   391 
       
   392 lemma lam_induct_strong:
       
   393   fixes a::"'a::fs_name"
       
   394   assumes a1: "\<And>name b. P b (Var name)"
       
   395   and     a2: "\<And>lam1 lam2 b. \<lbrakk>\<And>c. P c lam1; \<And>c. P c lam2\<rbrakk> \<Longrightarrow> P b (App lam1 lam2)"
       
   396   and     a3: "\<And>name lam b. \<lbrakk>\<And>c. P c lam; name \<sharp> b\<rbrakk> \<Longrightarrow> P b (Lam name lam)"
       
   397   shows "P a lam"
       
   398 proof -
       
   399   have "\<And>(pi::name prm) a. P a (pi \<bullet> lam)" 
       
   400   proof (induct lam rule: lam_induct)
       
   401     case (1 name pi)
       
   402     show "P a (pi \<bullet> Var name)"
       
   403       apply (simp)
       
   404       apply (rule a1)
       
   405       done
       
   406   next
       
   407     case (2 lam1 lam2 pi)
       
   408     have b1: "\<And>(pi::name prm) a. P a (pi \<bullet> lam1)" by fact
       
   409     have b2: "\<And>(pi::name prm) a. P a (pi \<bullet> lam2)" by fact
       
   410     show "P a (pi \<bullet> App lam1 lam2)"
       
   411       apply (simp)
       
   412       apply (rule a2)
       
   413       apply (rule b1)
       
   414       apply (rule b2)
       
   415       done
       
   416   next
       
   417     case (3 name lam pi a)
       
   418     have b: "\<And>(pi::name prm) a. P a (pi \<bullet> lam)" by fact
       
   419     obtain c::name where fr: "c\<sharp>(a, pi\<bullet>name, pi\<bullet>lam)"
       
   420       apply(rule exists_fresh[of "(a, pi\<bullet>name, pi\<bullet>lam)"])
       
   421       apply(simp_all add: fs_name1)
       
   422       done
       
   423     from b fr have p: "P a (Lam c (([(c, pi\<bullet>name)]@pi)\<bullet>lam))" 
       
   424       apply -
       
   425       apply(rule a3)
       
   426       apply(blast)
       
   427       apply(simp)
       
   428       done
       
   429     have eq: "[(c, pi\<bullet>name)] \<bullet> Lam (pi \<bullet> name) (pi \<bullet> lam) = Lam (pi \<bullet> name) (pi \<bullet> lam)"
       
   430       apply(rule perm_fresh_fresh)
       
   431       using fr
       
   432       apply(simp add: fresh_lam)
       
   433       apply(simp add: fresh_lam)
       
   434       done
       
   435     show "P a (pi \<bullet> Lam name lam)" 
       
   436       apply (simp)
       
   437       apply(subst eq[symmetric])
       
   438       using p
       
   439       apply(simp only: perm_lam pt_name2 swap_simps)
       
   440       done
       
   441   qed
       
   442   then have "P a (([]::name prm) \<bullet> lam)" by blast
       
   443   then show "P a lam" by simp 
       
   444 qed
       
   445 
       
   446 
       
   447 lemma var_fresh:
       
   448   fixes a::"name"
       
   449   shows "(a \<sharp> (Var b)) = (a \<sharp> b)"
       
   450   apply(simp add: fresh_def)
       
   451   apply(simp add: var_supp1)
       
   452   done
       
   453 
       
   454 (* lemma hom_reg: *)
       
   455 
       
   456 lemma rlam_rec_eqvt:
       
   457   fixes pi::"name prm"
       
   458   and   f1::"name \<Rightarrow> ('a::pt_name)"
       
   459   shows "(pi\<bullet>rlam_rec f1 f2 f3 t) = rlam_rec (pi\<bullet>f1) (pi\<bullet>f2) (pi\<bullet>f3) (pi\<bullet>t)"
       
   460 apply(induct t)
       
   461 apply(simp_all)
       
   462 apply(simp add: perm_fun_def)
       
   463 apply(perm_simp)
       
   464 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   465 back
       
   466 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   467 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   468 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   469 apply(simp)
       
   470 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   471 back
       
   472 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   473 apply(subst pt_fun_app_eq[OF pt_name_inst at_name_inst])
       
   474 apply(simp)
       
   475 done
       
   476  
       
   477 
       
   478 lemma rlam_rec_respects:
       
   479   assumes f1: "f_var \<in> Respects (op= ===> op=)"
       
   480   and     f2: "f_app \<in> Respects (alpha ===> alpha ===> op= ===> op= ===> op=)"
       
   481   and     f3: "f_lam \<in> Respects (op= ===> alpha ===> op= ===> op=)"
       
   482   shows "rlam_rec f_var f_app f_lam \<in> Respects (alpha ===> op =)"
       
   483 apply(simp add: mem_def)
       
   484 apply(simp add: Respects_def)
       
   485 apply(rule allI)
       
   486 apply(rule allI)
       
   487 apply(rule impI)
       
   488 apply(erule alpha.induct)
       
   489 apply(simp)
       
   490 apply(simp)
       
   491 using f2
       
   492 apply(simp add: mem_def)
       
   493 apply(simp add: Respects_def)
       
   494 using f3[simplified mem_def Respects_def]
       
   495 apply(simp)
       
   496 apply(case_tac "a=b")
       
   497 apply(clarify)
       
   498 apply(simp)
       
   499 (* probably true *)
       
   500 sorry
       
   501 
       
   502 function
       
   503   term1_hom :: "(name \<Rightarrow> 'a) \<Rightarrow>
       
   504                 (rlam \<Rightarrow> rlam \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> 'a) \<Rightarrow>
       
   505                 ((name \<Rightarrow> rlam) \<Rightarrow> (name \<Rightarrow> 'a) \<Rightarrow> 'a) \<Rightarrow> rlam \<Rightarrow> 'a"
       
   506 where
       
   507   "term1_hom var app abs' (rVar x) = (var x)"
       
   508 | "term1_hom var app abs' (rApp t u) =
       
   509      app t u (term1_hom var app abs' t) (term1_hom var app abs' u)"
       
   510 | "term1_hom var app abs' (rLam x u) =
       
   511      abs' (\<lambda>y. [(x, y)] \<bullet> u) (\<lambda>y. term1_hom var app abs' ([(x, y)] \<bullet> u))"
       
   512 apply(pat_completeness)
       
   513 apply(auto)
       
   514 done
       
   515 
       
   516 lemma pi_size:
       
   517   fixes pi::"name prm"
       
   518   and   t::"rlam"
       
   519   shows "size (pi \<bullet> t) = size t"
       
   520 apply(induct t)
       
   521 apply(auto)
       
   522 done
       
   523 
       
   524 termination term1_hom
       
   525   apply(relation "measure (\<lambda>(f1, f2, f3, t). size t)")
       
   526 apply(auto simp add: pi_size)
       
   527 done
       
   528 
       
   529 lemma lam_exhaust:
       
   530   "\<lbrakk>\<And>name. y = Var name \<Longrightarrow> P; \<And>rlam1 rlam2. y = App rlam1 rlam2 \<Longrightarrow> P; \<And>name rlam. y = Lam name rlam \<Longrightarrow> P\<rbrakk>
       
   531     \<Longrightarrow> P"
       
   532 apply(lifting rlam.exhaust)
       
   533 done
       
   534 
       
   535 (* THIS IS NOT TRUE, but it lets prove the existence of the hom function *)
       
   536 lemma lam_inject':
       
   537   "(Lam a x = Lam b y) = ((\<lambda>c. [(a, c)] \<bullet> x) = (\<lambda>c. [(b, c)] \<bullet> y))"
       
   538 sorry
       
   539 
       
   540 function
       
   541   hom :: "(name \<Rightarrow> 'a) \<Rightarrow>
       
   542                 (lam \<Rightarrow> lam \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> 'a) \<Rightarrow>
       
   543                 ((name \<Rightarrow> lam) \<Rightarrow> (name \<Rightarrow> 'a) \<Rightarrow> 'a) \<Rightarrow> lam \<Rightarrow> 'a"
       
   544 where
       
   545   "hom f_var f_app f_lam (Var x) = f_var x"
       
   546 | "hom f_var f_app f_lam (App l r) = f_app l r (hom f_var f_app f_lam l) (hom f_var f_app f_lam r)"
       
   547 | "hom f_var f_app f_lam (Lam a x) = f_lam (\<lambda>b. ([(a,b)] \<bullet> x)) (\<lambda>b. hom f_var f_app f_lam ([(a,b)] \<bullet> x))"
       
   548 defer
       
   549 apply(simp_all add: lam_inject') (* inject, distinct *)
       
   550 apply(tactic {* Cong_Tac.cong_tac @{thm cong} 1 *})
       
   551 apply(rule refl)
       
   552 apply(rule ext)
       
   553 apply(tactic {* Cong_Tac.cong_tac @{thm cong} 1 *})
       
   554 apply simp_all
       
   555 apply(erule conjE)+
       
   556 apply(rule_tac x="b" in cong)
       
   557 apply simp_all
       
   558 apply auto
       
   559 apply(rule_tac y="b" in lam_exhaust)
       
   560 apply simp_all
       
   561 apply auto
       
   562 apply meson
       
   563 apply(simp_all add: lam_inject')
       
   564 apply metis
       
   565 done
       
   566 
       
   567 termination hom
       
   568   apply -
       
   569 (*
       
   570 ML_prf {* Size.size_thms @{theory} "LamEx.lam" *}
       
   571 *)
       
   572 sorry
       
   573 
       
   574 thm hom.simps
       
   575 
       
   576 lemma term1_hom_rsp:
       
   577   "\<lbrakk>(alpha ===> alpha ===> op =) f_app f_app; ((op = ===> alpha) ===> op =) f_lam f_lam\<rbrakk>
       
   578        \<Longrightarrow> (alpha ===> op =) (term1_hom f_var f_app f_lam) (term1_hom f_var f_app f_lam)"
       
   579 apply(simp)
       
   580 apply(rule allI)+
       
   581 apply(rule impI)
       
   582 apply(erule alpha.induct)
       
   583 apply(auto)[1]
       
   584 apply(auto)[1]
       
   585 apply(simp)
       
   586 apply(erule conjE)+
       
   587 apply(erule exE)+
       
   588 apply(erule conjE)+
       
   589 apply(clarify)
       
   590 sorry
       
   591 
       
   592 lemma hom: "
       
   593 \<forall>f_var. \<forall>f_app \<in> Respects(alpha ===> alpha ===> op =).
       
   594 \<forall>f_lam \<in> Respects((op = ===> alpha) ===> op =).
       
   595 \<exists>hom\<in>Respects (alpha ===> op =). 
       
   596     ((\<forall>x. hom (rVar x) = f_var x) \<and>
       
   597      (\<forall>l r. hom (rApp l r) = f_app l r (hom l) (hom r)) \<and>
       
   598      (\<forall>x a. hom (rLam a x) = f_lam (\<lambda>b. ([(a,b)]\<bullet> x)) (\<lambda>b. hom ([(a,b)] \<bullet> x))))"
       
   599 apply(rule allI)
       
   600 apply(rule ballI)+
       
   601 apply(rule_tac x="term1_hom f_var f_app f_lam" in bexI)
       
   602 apply(simp_all)
       
   603 apply(simp only: in_respects)
       
   604 apply(rule term1_hom_rsp)
       
   605 apply(assumption)+
       
   606 done
       
   607 
       
   608 lemma hom':
       
   609 "\<exists>hom.
       
   610   ((\<forall>x. hom (Var x) = f_var x) \<and>
       
   611    (\<forall>l r. hom (App l r) = f_app l r (hom l) (hom r)) \<and>
       
   612    (\<forall>x a. hom (Lam a x) = f_lam (\<lambda>b. ([(a,b)] \<bullet> x)) (\<lambda>b. hom ([(a,b)] \<bullet> x))))"
       
   613 apply (lifting hom)
       
   614 done
       
   615 
       
   616 (* test test
       
   617 lemma raw_hom_correct: 
       
   618   assumes f1: "f_var \<in> Respects (op= ===> op=)"
       
   619   and     f2: "f_app \<in> Respects (alpha ===> alpha ===> op= ===> op= ===> op=)"
       
   620   and     f3: "f_lam \<in> Respects ((op= ===> alpha) ===> (op= ===> op=) ===> op=)"
       
   621   shows "\<exists>!hom\<in>Respects (alpha ===> op =). 
       
   622     ((\<forall>x. hom (rVar x) = f_var x) \<and>
       
   623      (\<forall>l r. hom (rApp l r) = f_app l r (hom l) (hom r)) \<and>
       
   624      (\<forall>x a. hom (rLam a x) = f_lam (\<lambda>b. ([(a,b)]\<bullet> x)) (\<lambda>b. hom ([(a,b)] \<bullet> x))))"
       
   625 unfolding Bex1_def
       
   626 apply(rule ex1I)
       
   627 sorry
       
   628 *)
       
   629 
       
   630 
       
   631 end
       
   632