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