src/HOL/Nominal/Examples/Type_Preservation.thy
author haftmann
Fri, 22 Jan 2010 13:38:29 +0100
changeset 34945 478f31081a78
parent 29097 68245155eb58
child 37358 74fb4f03bb51
permissions -rw-r--r--
more accurate dependencies
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
     1
theory Type_Preservation
6fd85edc403d new example
urbanc
parents:
diff changeset
     2
  imports Nominal
6fd85edc403d new example
urbanc
parents:
diff changeset
     3
begin
6fd85edc403d new example
urbanc
parents:
diff changeset
     4
27160
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
     5
text {*
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
     6
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
     7
  This theory shows how to prove the type preservation
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
     8
  property for the simply-typed lambda-calculus and 
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
     9
  beta-reduction.
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
    10
 
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
    11
*}
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
    12
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
    13
atom_decl name
6fd85edc403d new example
urbanc
parents:
diff changeset
    14
6fd85edc403d new example
urbanc
parents:
diff changeset
    15
nominal_datatype lam =
6fd85edc403d new example
urbanc
parents:
diff changeset
    16
  Var "name"
6fd85edc403d new example
urbanc
parents:
diff changeset
    17
| App "lam" "lam" 
6fd85edc403d new example
urbanc
parents:
diff changeset
    18
| Lam "\<guillemotleft>name\<guillemotright>lam" ("Lam [_]._")
6fd85edc403d new example
urbanc
parents:
diff changeset
    19
6fd85edc403d new example
urbanc
parents:
diff changeset
    20
text {* Capture-Avoiding Substitution *}
6fd85edc403d new example
urbanc
parents:
diff changeset
    21
29097
68245155eb58 Modified nominal_primrec to make it work with local theories, unified syntax
berghofe
parents: 27160
diff changeset
    22
nominal_primrec
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
    23
  subst :: "lam \<Rightarrow> name \<Rightarrow> lam \<Rightarrow> lam"  ("_[_::=_]")
29097
68245155eb58 Modified nominal_primrec to make it work with local theories, unified syntax
berghofe
parents: 27160
diff changeset
    24
where
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
    25
  "(Var x)[y::=s] = (if x=y then s else (Var x))"
29097
68245155eb58 Modified nominal_primrec to make it work with local theories, unified syntax
berghofe
parents: 27160
diff changeset
    26
| "(App t\<^isub>1 t\<^isub>2)[y::=s] = App (t\<^isub>1[y::=s]) (t\<^isub>2[y::=s])"
68245155eb58 Modified nominal_primrec to make it work with local theories, unified syntax
berghofe
parents: 27160
diff changeset
    27
| "x\<sharp>(y,s) \<Longrightarrow> (Lam [x].t)[y::=s] = Lam [x].(t[y::=s])"
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
    28
apply(finite_guess)+
6fd85edc403d new example
urbanc
parents:
diff changeset
    29
apply(rule TrueI)+
6fd85edc403d new example
urbanc
parents:
diff changeset
    30
apply(simp add: abs_fresh)
6fd85edc403d new example
urbanc
parents:
diff changeset
    31
apply(fresh_guess)+
6fd85edc403d new example
urbanc
parents:
diff changeset
    32
done
6fd85edc403d new example
urbanc
parents:
diff changeset
    33
6fd85edc403d new example
urbanc
parents:
diff changeset
    34
lemma  subst_eqvt[eqvt]:
6fd85edc403d new example
urbanc
parents:
diff changeset
    35
  fixes pi::"name prm"
6fd85edc403d new example
urbanc
parents:
diff changeset
    36
  shows "pi\<bullet>(t1[x::=t2]) = (pi\<bullet>t1)[(pi\<bullet>x)::=(pi\<bullet>t2)]"
6fd85edc403d new example
urbanc
parents:
diff changeset
    37
by (nominal_induct t1 avoiding: x t2 rule: lam.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
    38
   (auto simp add: perm_bij fresh_atm fresh_bij)
6fd85edc403d new example
urbanc
parents:
diff changeset
    39
6fd85edc403d new example
urbanc
parents:
diff changeset
    40
lemma fresh_fact:
6fd85edc403d new example
urbanc
parents:
diff changeset
    41
  fixes z::"name"
6fd85edc403d new example
urbanc
parents:
diff changeset
    42
  shows "\<lbrakk>z\<sharp>s; (z=y \<or> z\<sharp>t)\<rbrakk> \<Longrightarrow> z\<sharp>t[y::=s]"
6fd85edc403d new example
urbanc
parents:
diff changeset
    43
by (nominal_induct t avoiding: z y s rule: lam.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
    44
   (auto simp add: abs_fresh fresh_prod fresh_atm)
6fd85edc403d new example
urbanc
parents:
diff changeset
    45
6fd85edc403d new example
urbanc
parents:
diff changeset
    46
text {* Types *}
6fd85edc403d new example
urbanc
parents:
diff changeset
    47
6fd85edc403d new example
urbanc
parents:
diff changeset
    48
nominal_datatype ty =
6fd85edc403d new example
urbanc
parents:
diff changeset
    49
    TVar "string"
6fd85edc403d new example
urbanc
parents:
diff changeset
    50
  | TArr "ty" "ty" ("_ \<rightarrow> _")
6fd85edc403d new example
urbanc
parents:
diff changeset
    51
6fd85edc403d new example
urbanc
parents:
diff changeset
    52
lemma ty_fresh:
6fd85edc403d new example
urbanc
parents:
diff changeset
    53
  fixes x::"name"
6fd85edc403d new example
urbanc
parents:
diff changeset
    54
  and   T::"ty"
6fd85edc403d new example
urbanc
parents:
diff changeset
    55
  shows "x\<sharp>T"
6fd85edc403d new example
urbanc
parents:
diff changeset
    56
by (induct T rule: ty.induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
    57
   (auto simp add: fresh_string)
6fd85edc403d new example
urbanc
parents:
diff changeset
    58
6fd85edc403d new example
urbanc
parents:
diff changeset
    59
text {* Typing Contexts *}
6fd85edc403d new example
urbanc
parents:
diff changeset
    60
6fd85edc403d new example
urbanc
parents:
diff changeset
    61
types ctx = "(name\<times>ty) list"
6fd85edc403d new example
urbanc
parents:
diff changeset
    62
6fd85edc403d new example
urbanc
parents:
diff changeset
    63
abbreviation
6fd85edc403d new example
urbanc
parents:
diff changeset
    64
  "sub_ctx" :: "ctx \<Rightarrow> ctx \<Rightarrow> bool" ("_ \<subseteq> _") 
6fd85edc403d new example
urbanc
parents:
diff changeset
    65
where
6fd85edc403d new example
urbanc
parents:
diff changeset
    66
  "\<Gamma>\<^isub>1 \<subseteq> \<Gamma>\<^isub>2 \<equiv> \<forall>x. x \<in> set \<Gamma>\<^isub>1 \<longrightarrow> x \<in> set \<Gamma>\<^isub>2"
6fd85edc403d new example
urbanc
parents:
diff changeset
    67
27160
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
    68
text {* Validity of Typing Contexts *}
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
    69
6fd85edc403d new example
urbanc
parents:
diff changeset
    70
inductive
6fd85edc403d new example
urbanc
parents:
diff changeset
    71
  valid :: "(name\<times>ty) list \<Rightarrow> bool"
6fd85edc403d new example
urbanc
parents:
diff changeset
    72
where
6fd85edc403d new example
urbanc
parents:
diff changeset
    73
    v1[intro]: "valid []"
6fd85edc403d new example
urbanc
parents:
diff changeset
    74
  | v2[intro]: "\<lbrakk>valid \<Gamma>; x\<sharp>\<Gamma>\<rbrakk>\<Longrightarrow> valid ((x,T)#\<Gamma>)"
6fd85edc403d new example
urbanc
parents:
diff changeset
    75
6fd85edc403d new example
urbanc
parents:
diff changeset
    76
equivariance valid
6fd85edc403d new example
urbanc
parents:
diff changeset
    77
6fd85edc403d new example
urbanc
parents:
diff changeset
    78
lemma valid_elim[dest]:
6fd85edc403d new example
urbanc
parents:
diff changeset
    79
  assumes a: "valid ((x,T)#\<Gamma>)"
6fd85edc403d new example
urbanc
parents:
diff changeset
    80
  shows "x\<sharp>\<Gamma> \<and> valid \<Gamma>"
6fd85edc403d new example
urbanc
parents:
diff changeset
    81
using a by (cases) (auto)
6fd85edc403d new example
urbanc
parents:
diff changeset
    82
6fd85edc403d new example
urbanc
parents:
diff changeset
    83
lemma valid_insert:
6fd85edc403d new example
urbanc
parents:
diff changeset
    84
  assumes a: "valid (\<Delta>@[(x,T)]@\<Gamma>)"
6fd85edc403d new example
urbanc
parents:
diff changeset
    85
  shows "valid (\<Delta> @ \<Gamma>)" 
6fd85edc403d new example
urbanc
parents:
diff changeset
    86
using a
6fd85edc403d new example
urbanc
parents:
diff changeset
    87
by (induct \<Delta>)
6fd85edc403d new example
urbanc
parents:
diff changeset
    88
   (auto simp add:  fresh_list_append fresh_list_cons dest!: valid_elim)
6fd85edc403d new example
urbanc
parents:
diff changeset
    89
6fd85edc403d new example
urbanc
parents:
diff changeset
    90
lemma fresh_set: 
6fd85edc403d new example
urbanc
parents:
diff changeset
    91
  shows "y\<sharp>xs = (\<forall>x\<in>set xs. y\<sharp>x)"
6fd85edc403d new example
urbanc
parents:
diff changeset
    92
by (induct xs) (simp_all add: fresh_list_nil fresh_list_cons)
6fd85edc403d new example
urbanc
parents:
diff changeset
    93
6fd85edc403d new example
urbanc
parents:
diff changeset
    94
lemma context_unique:
6fd85edc403d new example
urbanc
parents:
diff changeset
    95
  assumes a1: "valid \<Gamma>"
6fd85edc403d new example
urbanc
parents:
diff changeset
    96
  and     a2: "(x,T) \<in> set \<Gamma>"
6fd85edc403d new example
urbanc
parents:
diff changeset
    97
  and     a3: "(x,U) \<in> set \<Gamma>"
6fd85edc403d new example
urbanc
parents:
diff changeset
    98
  shows "T = U" 
6fd85edc403d new example
urbanc
parents:
diff changeset
    99
using a1 a2 a3
6fd85edc403d new example
urbanc
parents:
diff changeset
   100
by (induct) (auto simp add: fresh_set fresh_prod fresh_atm)
6fd85edc403d new example
urbanc
parents:
diff changeset
   101
27160
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
   102
text {* Typing Relation *}
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
   103
6fd85edc403d new example
urbanc
parents:
diff changeset
   104
inductive
6fd85edc403d new example
urbanc
parents:
diff changeset
   105
  typing :: "ctx \<Rightarrow> lam \<Rightarrow> ty \<Rightarrow> bool" ("_ \<turnstile> _ : _") 
6fd85edc403d new example
urbanc
parents:
diff changeset
   106
where
6fd85edc403d new example
urbanc
parents:
diff changeset
   107
  t_Var[intro]: "\<lbrakk>valid \<Gamma>; (x,T)\<in>set \<Gamma>\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Var x : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   108
| t_App[intro]: "\<lbrakk>\<Gamma> \<turnstile> t\<^isub>1 : T\<^isub>1\<rightarrow>T\<^isub>2; \<Gamma> \<turnstile> t\<^isub>2 : T\<^isub>1\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> App t\<^isub>1 t\<^isub>2 : T\<^isub>2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   109
| t_Lam[intro]: "\<lbrakk>x\<sharp>\<Gamma>; (x,T\<^isub>1)#\<Gamma> \<turnstile> t : T\<^isub>2\<rbrakk> \<Longrightarrow> \<Gamma> \<turnstile> Lam [x].t : T\<^isub>1\<rightarrow>T\<^isub>2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   110
6fd85edc403d new example
urbanc
parents:
diff changeset
   111
equivariance typing
6fd85edc403d new example
urbanc
parents:
diff changeset
   112
nominal_inductive typing
6fd85edc403d new example
urbanc
parents:
diff changeset
   113
  by (simp_all add: abs_fresh ty_fresh)
6fd85edc403d new example
urbanc
parents:
diff changeset
   114
6fd85edc403d new example
urbanc
parents:
diff changeset
   115
lemma t_Lam_inversion[dest]:
6fd85edc403d new example
urbanc
parents:
diff changeset
   116
  assumes ty: "\<Gamma> \<turnstile> Lam [x].t : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   117
  and     fc: "x\<sharp>\<Gamma>" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   118
  shows "\<exists>T\<^isub>1 T\<^isub>2. T = T\<^isub>1 \<rightarrow> T\<^isub>2 \<and> (x,T\<^isub>1)#\<Gamma> \<turnstile> t : T\<^isub>2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   119
using ty fc 
6fd85edc403d new example
urbanc
parents:
diff changeset
   120
by (cases rule: typing.strong_cases) 
6fd85edc403d new example
urbanc
parents:
diff changeset
   121
   (auto simp add: alpha lam.inject abs_fresh ty_fresh)
6fd85edc403d new example
urbanc
parents:
diff changeset
   122
6fd85edc403d new example
urbanc
parents:
diff changeset
   123
lemma t_App_inversion[dest]:
6fd85edc403d new example
urbanc
parents:
diff changeset
   124
  assumes ty: "\<Gamma> \<turnstile> App t1 t2 : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   125
  shows "\<exists>T'. \<Gamma> \<turnstile> t1 : T' \<rightarrow> T \<and> \<Gamma> \<turnstile> t2 : T'"
6fd85edc403d new example
urbanc
parents:
diff changeset
   126
using ty 
6fd85edc403d new example
urbanc
parents:
diff changeset
   127
by (cases) (auto simp add: lam.inject)
6fd85edc403d new example
urbanc
parents:
diff changeset
   128
6fd85edc403d new example
urbanc
parents:
diff changeset
   129
lemma weakening: 
6fd85edc403d new example
urbanc
parents:
diff changeset
   130
  fixes \<Gamma>1 \<Gamma>2::"ctx"
6fd85edc403d new example
urbanc
parents:
diff changeset
   131
  assumes a: "\<Gamma>1 \<turnstile> t : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   132
  and     b: "valid \<Gamma>2" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   133
  and     c: "\<Gamma>1 \<subseteq> \<Gamma>2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   134
  shows "\<Gamma>2 \<turnstile> t : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   135
using a b c
6fd85edc403d new example
urbanc
parents:
diff changeset
   136
by (nominal_induct \<Gamma>1 t T avoiding: \<Gamma>2 rule: typing.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
   137
   (auto | atomize)+
6fd85edc403d new example
urbanc
parents:
diff changeset
   138
6fd85edc403d new example
urbanc
parents:
diff changeset
   139
lemma type_substitution_aux:
6fd85edc403d new example
urbanc
parents:
diff changeset
   140
  assumes a: "(\<Delta>@[(x,T')]@\<Gamma>) \<turnstile> e : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   141
  and     b: "\<Gamma> \<turnstile> e' : T'"
6fd85edc403d new example
urbanc
parents:
diff changeset
   142
  shows "(\<Delta>@\<Gamma>) \<turnstile> e[x::=e'] : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   143
using a b 
6fd85edc403d new example
urbanc
parents:
diff changeset
   144
proof (nominal_induct \<Gamma>'\<equiv>"\<Delta>@[(x,T')]@\<Gamma>" e T avoiding: x e' \<Delta> rule: typing.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
   145
  case (t_Var \<Gamma>' y T x e' \<Delta>)
6fd85edc403d new example
urbanc
parents:
diff changeset
   146
  then have a1: "valid (\<Delta>@[(x,T')]@\<Gamma>)" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   147
       and  a2: "(y,T) \<in> set (\<Delta>@[(x,T')]@\<Gamma>)" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   148
       and  a3: "\<Gamma> \<turnstile> e' : T'" by simp_all
6fd85edc403d new example
urbanc
parents:
diff changeset
   149
  from a1 have a4: "valid (\<Delta>@\<Gamma>)" by (rule valid_insert)
6fd85edc403d new example
urbanc
parents:
diff changeset
   150
  { assume eq: "x=y"
6fd85edc403d new example
urbanc
parents:
diff changeset
   151
    from a1 a2 have "T=T'" using eq by (auto intro: context_unique)
6fd85edc403d new example
urbanc
parents:
diff changeset
   152
    with a3 have "\<Delta>@\<Gamma> \<turnstile> Var y[x::=e'] : T" using eq a4 by (auto intro: weakening)
6fd85edc403d new example
urbanc
parents:
diff changeset
   153
  }
6fd85edc403d new example
urbanc
parents:
diff changeset
   154
  moreover
6fd85edc403d new example
urbanc
parents:
diff changeset
   155
  { assume ineq: "x\<noteq>y"
6fd85edc403d new example
urbanc
parents:
diff changeset
   156
    from a2 have "(y,T) \<in> set (\<Delta>@\<Gamma>)" using ineq by simp
6fd85edc403d new example
urbanc
parents:
diff changeset
   157
    then have "\<Delta>@\<Gamma> \<turnstile> Var y[x::=e'] : T" using ineq a4 by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   158
  }
6fd85edc403d new example
urbanc
parents:
diff changeset
   159
  ultimately show "\<Delta>@\<Gamma> \<turnstile> Var y[x::=e'] : T" by blast
6fd85edc403d new example
urbanc
parents:
diff changeset
   160
qed (force simp add: fresh_list_append fresh_list_cons)+
6fd85edc403d new example
urbanc
parents:
diff changeset
   161
6fd85edc403d new example
urbanc
parents:
diff changeset
   162
corollary type_substitution:
6fd85edc403d new example
urbanc
parents:
diff changeset
   163
  assumes a: "(x,T')#\<Gamma> \<turnstile> e : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   164
  and     b: "\<Gamma> \<turnstile> e' : T'"
6fd85edc403d new example
urbanc
parents:
diff changeset
   165
  shows "\<Gamma> \<turnstile> e[x::=e'] : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   166
using a b
6fd85edc403d new example
urbanc
parents:
diff changeset
   167
by (auto intro: type_substitution_aux[where \<Delta>="[]",simplified])
6fd85edc403d new example
urbanc
parents:
diff changeset
   168
27160
1ef88d06362f tuned header and comments
urbanc
parents: 27032
diff changeset
   169
text {* Beta Reduction *}
27032
6fd85edc403d new example
urbanc
parents:
diff changeset
   170
6fd85edc403d new example
urbanc
parents:
diff changeset
   171
inductive 
6fd85edc403d new example
urbanc
parents:
diff changeset
   172
  "beta" :: "lam\<Rightarrow>lam\<Rightarrow>bool" (" _ \<longrightarrow>\<^isub>\<beta> _")
6fd85edc403d new example
urbanc
parents:
diff changeset
   173
where
6fd85edc403d new example
urbanc
parents:
diff changeset
   174
  b1[intro]: "t1 \<longrightarrow>\<^isub>\<beta> t2 \<Longrightarrow> App t1 s \<longrightarrow>\<^isub>\<beta> App t2 s"
6fd85edc403d new example
urbanc
parents:
diff changeset
   175
| b2[intro]: "s1 \<longrightarrow>\<^isub>\<beta> s2 \<Longrightarrow> App t s1 \<longrightarrow>\<^isub>\<beta> App t s2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   176
| b3[intro]: "t1 \<longrightarrow>\<^isub>\<beta> t2 \<Longrightarrow> Lam [x].t1 \<longrightarrow>\<^isub>\<beta> Lam [x].t2"
6fd85edc403d new example
urbanc
parents:
diff changeset
   177
| b4[intro]: "x\<sharp>s \<Longrightarrow> App (Lam [x].t) s \<longrightarrow>\<^isub>\<beta> t[x::=s]"
6fd85edc403d new example
urbanc
parents:
diff changeset
   178
6fd85edc403d new example
urbanc
parents:
diff changeset
   179
equivariance beta
6fd85edc403d new example
urbanc
parents:
diff changeset
   180
nominal_inductive beta
6fd85edc403d new example
urbanc
parents:
diff changeset
   181
  by (auto simp add: abs_fresh fresh_fact)
6fd85edc403d new example
urbanc
parents:
diff changeset
   182
6fd85edc403d new example
urbanc
parents:
diff changeset
   183
6fd85edc403d new example
urbanc
parents:
diff changeset
   184
theorem type_preservation:
6fd85edc403d new example
urbanc
parents:
diff changeset
   185
  assumes a: "t \<longrightarrow>\<^isub>\<beta> t'"
6fd85edc403d new example
urbanc
parents:
diff changeset
   186
  and     b: "\<Gamma> \<turnstile> t : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   187
  shows "\<Gamma> \<turnstile> t' : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   188
using a b
6fd85edc403d new example
urbanc
parents:
diff changeset
   189
proof (nominal_induct avoiding: \<Gamma> T rule: beta.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
   190
  case (b1 t1 t2 s \<Gamma> T)
6fd85edc403d new example
urbanc
parents:
diff changeset
   191
  have "\<Gamma> \<turnstile> App t1 s : T" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   192
  then obtain T' where a1: "\<Gamma> \<turnstile> t1 : T' \<rightarrow> T" and a2: "\<Gamma> \<turnstile> s : T'" by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   193
  have ih: "\<Gamma> \<turnstile> t1 : T' \<rightarrow> T \<Longrightarrow> \<Gamma> \<turnstile> t2 : T' \<rightarrow> T" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   194
  with a1 a2 show "\<Gamma> \<turnstile> App t2 s : T" by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   195
next 
6fd85edc403d new example
urbanc
parents:
diff changeset
   196
  case (b2 s1 s2 t \<Gamma> T)
6fd85edc403d new example
urbanc
parents:
diff changeset
   197
  have "\<Gamma> \<turnstile> App t s1 : T" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   198
  then obtain T' where a1: "\<Gamma> \<turnstile> t : T' \<rightarrow> T" and a2: "\<Gamma> \<turnstile> s1 : T'" by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   199
  have ih: "\<Gamma> \<turnstile> s1 : T' \<Longrightarrow> \<Gamma> \<turnstile> s2 : T'" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   200
  with a1 a2 show "\<Gamma> \<turnstile> App t s2 : T" by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   201
next 
6fd85edc403d new example
urbanc
parents:
diff changeset
   202
  case (b3 t1 t2 x \<Gamma> T)
6fd85edc403d new example
urbanc
parents:
diff changeset
   203
  have vc: "x\<sharp>\<Gamma>" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   204
  have "\<Gamma> \<turnstile> Lam [x].t1 : T" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   205
  then obtain T1 T2 where a1: "(x,T1)#\<Gamma> \<turnstile> t1 : T2" and a2: "T = T1 \<rightarrow> T2" using vc by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   206
  have ih: "(x,T1)#\<Gamma> \<turnstile> t1 : T2 \<Longrightarrow> (x,T1)#\<Gamma> \<turnstile> t2 : T2" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   207
  with a1 a2 show "\<Gamma> \<turnstile> Lam [x].t2 : T" using vc by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   208
next
6fd85edc403d new example
urbanc
parents:
diff changeset
   209
  case (b4 x s t \<Gamma> T)
6fd85edc403d new example
urbanc
parents:
diff changeset
   210
  have vc: "x\<sharp>\<Gamma>" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   211
  have "\<Gamma> \<turnstile> App (Lam [x].t) s : T" by fact
6fd85edc403d new example
urbanc
parents:
diff changeset
   212
  then obtain T' where a1: "\<Gamma> \<turnstile> Lam [x].t : T' \<rightarrow> T" and a2: "\<Gamma> \<turnstile> s : T'" by auto
6fd85edc403d new example
urbanc
parents:
diff changeset
   213
  from a1 obtain T1 T2 where a3: "(x,T')#\<Gamma> \<turnstile> t : T" using vc by (auto simp add: ty.inject)
6fd85edc403d new example
urbanc
parents:
diff changeset
   214
  from a3 a2 show "\<Gamma> \<turnstile> t[x::=s] : T" by (simp add: type_substitution)
6fd85edc403d new example
urbanc
parents:
diff changeset
   215
qed
6fd85edc403d new example
urbanc
parents:
diff changeset
   216
6fd85edc403d new example
urbanc
parents:
diff changeset
   217
6fd85edc403d new example
urbanc
parents:
diff changeset
   218
theorem type_preservation_automatic:
6fd85edc403d new example
urbanc
parents:
diff changeset
   219
  assumes a: "t \<longrightarrow>\<^isub>\<beta> t'"
6fd85edc403d new example
urbanc
parents:
diff changeset
   220
  and     b: "\<Gamma> \<turnstile> t : T" 
6fd85edc403d new example
urbanc
parents:
diff changeset
   221
  shows "\<Gamma> \<turnstile> t' : T"
6fd85edc403d new example
urbanc
parents:
diff changeset
   222
using a b
6fd85edc403d new example
urbanc
parents:
diff changeset
   223
by (nominal_induct avoiding: \<Gamma> T rule: beta.strong_induct)
6fd85edc403d new example
urbanc
parents:
diff changeset
   224
   (auto dest!: t_Lam_inversion t_App_inversion simp add: ty.inject type_substitution)
6fd85edc403d new example
urbanc
parents:
diff changeset
   225
6fd85edc403d new example
urbanc
parents:
diff changeset
   226
end