src/HOL/W0/W0.thy
author kleing
Mon Jun 21 10:25:57 2004 +0200 (2004-06-21)
changeset 14981 e73f8140af78
parent 13890 90611b4e0054
child 15140 322485b816ac
permissions -rw-r--r--
Merged in license change from Isabelle2004
wenzelm@12944
     1
(*  Title:      HOL/W0/W0.thy
wenzelm@12944
     2
    ID:         $Id$
wenzelm@12945
     3
    Author:     Dieter Nazareth, Tobias Nipkow, Thomas Stauner, Markus Wenzel
wenzelm@12944
     4
*)
wenzelm@12944
     5
wenzelm@12944
     6
theory W0 = Main:
wenzelm@12944
     7
wenzelm@12944
     8
section {* Universal error monad *}
wenzelm@12944
     9
wenzelm@12944
    10
datatype 'a maybe = Ok 'a | Fail
wenzelm@12944
    11
wenzelm@12944
    12
constdefs
wenzelm@12944
    13
  bind :: "'a maybe \<Rightarrow> ('a \<Rightarrow> 'b maybe) \<Rightarrow> 'b maybe"    (infixl "\<bind>" 60)
wenzelm@12944
    14
  "m \<bind> f \<equiv> case m of Ok r \<Rightarrow> f r | Fail \<Rightarrow> Fail"
wenzelm@12944
    15
wenzelm@12944
    16
syntax
wenzelm@12944
    17
  "_bind" :: "patterns \<Rightarrow> 'a maybe \<Rightarrow> 'b \<Rightarrow> 'c"    ("(_ := _;//_)" 0)
wenzelm@12944
    18
translations
wenzelm@12944
    19
  "P := E; F" == "E \<bind> (\<lambda>P. F)"
wenzelm@12944
    20
wenzelm@12944
    21
lemma bind_Ok [simp]: "(Ok s) \<bind> f = (f s)"
wenzelm@12944
    22
  by (simp add: bind_def)
wenzelm@12944
    23
wenzelm@12944
    24
lemma bind_Fail [simp]: "Fail \<bind> f = Fail"
wenzelm@12944
    25
  by (simp add: bind_def)
wenzelm@12944
    26
wenzelm@12944
    27
lemma split_bind:
wenzelm@12944
    28
    "P (res \<bind> f) = ((res = Fail \<longrightarrow> P Fail) \<and> (\<forall>s. res = Ok s \<longrightarrow> P (f s)))"
wenzelm@12944
    29
  by (induct res) simp_all
wenzelm@12944
    30
wenzelm@12944
    31
lemma split_bind_asm:
wenzelm@12944
    32
  "P (res \<bind> f) = (\<not> (res = Fail \<and> \<not> P Fail \<or> (\<exists>s. res = Ok s \<and> \<not> P (f s))))"
wenzelm@12944
    33
  by (simp split: split_bind)
wenzelm@12944
    34
wenzelm@12944
    35
lemmas bind_splits = split_bind split_bind_asm
wenzelm@12944
    36
wenzelm@12944
    37
lemma bind_eq_Fail [simp]:
wenzelm@12944
    38
  "((m \<bind> f) = Fail) = ((m = Fail) \<or> (\<exists>p. m = Ok p \<and> f p = Fail))"
wenzelm@12944
    39
  by (simp split: split_bind)
wenzelm@12944
    40
wenzelm@12944
    41
lemma rotate_Ok: "(y = Ok x) = (Ok x = y)"
wenzelm@12944
    42
  by (rule eq_sym_conv)
wenzelm@12944
    43
wenzelm@12944
    44
wenzelm@12944
    45
section {* MiniML-types and type substitutions *}
wenzelm@12944
    46
wenzelm@12944
    47
axclass type_struct \<subseteq> type
wenzelm@12944
    48
  -- {* new class for structures containing type variables *}
wenzelm@12944
    49
wenzelm@12944
    50
datatype "typ" = TVar nat | TFun "typ" "typ"    (infixr "->" 70)
wenzelm@12944
    51
  -- {* type expressions *}
wenzelm@12944
    52
wenzelm@12944
    53
types subst = "nat => typ"
wenzelm@12944
    54
  -- {* type variable substitution *}
wenzelm@12944
    55
wenzelm@12944
    56
instance "typ" :: type_struct ..
wenzelm@12944
    57
instance list :: (type_struct) type_struct ..
wenzelm@12944
    58
instance fun :: (type, type_struct) type_struct ..
wenzelm@12944
    59
wenzelm@12944
    60
wenzelm@12944
    61
subsection {* Substitutions *}
wenzelm@12944
    62
wenzelm@12944
    63
consts
wenzelm@12944
    64
  app_subst :: "subst \<Rightarrow> 'a::type_struct \<Rightarrow> 'a::type_struct"    ("$")
wenzelm@12944
    65
  -- {* extension of substitution to type structures *}
wenzelm@13537
    66
primrec (app_subst_typ)
wenzelm@12944
    67
  app_subst_TVar: "$s (TVar n) = s n"
wenzelm@12944
    68
  app_subst_Fun: "$s (t1 -> t2) = $s t1 -> $s t2"
wenzelm@12944
    69
wenzelm@12944
    70
defs (overloaded)
wenzelm@12944
    71
  app_subst_list: "$s \<equiv> map ($s)"
wenzelm@12944
    72
wenzelm@12944
    73
consts
wenzelm@12944
    74
  free_tv :: "'a::type_struct \<Rightarrow> nat set"
wenzelm@12944
    75
  -- {* @{text "free_tv s"}: the type variables occuring freely in the type structure @{text s} *}
wenzelm@12944
    76
wenzelm@13537
    77
primrec (free_tv_typ)
wenzelm@12944
    78
  "free_tv (TVar m) = {m}"
wenzelm@12944
    79
  "free_tv (t1 -> t2) = free_tv t1 \<union> free_tv t2"
wenzelm@12944
    80
wenzelm@13537
    81
primrec (free_tv_list)
wenzelm@12944
    82
  "free_tv [] = {}"
wenzelm@12944
    83
  "free_tv (x # xs) = free_tv x \<union> free_tv xs"
wenzelm@12944
    84
wenzelm@12944
    85
constdefs
wenzelm@12944
    86
  dom :: "subst \<Rightarrow> nat set"
wenzelm@12944
    87
  "dom s \<equiv> {n. s n \<noteq> TVar n}"
wenzelm@12944
    88
  -- {* domain of a substitution *}
wenzelm@12944
    89
wenzelm@12944
    90
  cod :: "subst \<Rightarrow> nat set"
wenzelm@12944
    91
  "cod s \<equiv> \<Union>m \<in> dom s. free_tv (s m)"
wenzelm@12944
    92
  -- {* codomain of a substitutions: the introduced variables *}
wenzelm@12944
    93
wenzelm@12944
    94
defs
wenzelm@12944
    95
  free_tv_subst: "free_tv s \<equiv> dom s \<union> cod s"
wenzelm@12944
    96
wenzelm@12944
    97
text {*
wenzelm@12944
    98
  @{text "new_tv s n"} checks whether @{text n} is a new type variable
wenzelm@12944
    99
  wrt.\ a type structure @{text s}, i.e.\ whether @{text n} is greater
wenzelm@12944
   100
  than any type variable occuring in the type structure.
wenzelm@12944
   101
*}
wenzelm@12944
   102
wenzelm@12944
   103
constdefs
wenzelm@12944
   104
  new_tv :: "nat \<Rightarrow> 'a::type_struct \<Rightarrow> bool"
wenzelm@12944
   105
  "new_tv n ts \<equiv> \<forall>m. m \<in> free_tv ts \<longrightarrow> m < n"
wenzelm@12944
   106
wenzelm@12944
   107
wenzelm@12944
   108
subsubsection {* Identity substitution *}
wenzelm@12944
   109
wenzelm@12944
   110
constdefs
wenzelm@12944
   111
  id_subst :: subst
wenzelm@12944
   112
  "id_subst \<equiv> \<lambda>n. TVar n"
wenzelm@12944
   113
wenzelm@12944
   114
lemma app_subst_id_te [simp]:
wenzelm@12944
   115
  "$id_subst = (\<lambda>t::typ. t)"
wenzelm@12944
   116
  -- {* application of @{text id_subst} does not change type expression *}
wenzelm@12944
   117
proof
wenzelm@12944
   118
  fix t :: "typ"
wenzelm@12944
   119
  show "$id_subst t = t"
wenzelm@12944
   120
    by (induct t) (simp_all add: id_subst_def)
wenzelm@12944
   121
qed
wenzelm@12944
   122
wenzelm@12944
   123
lemma app_subst_id_tel [simp]: "$id_subst = (\<lambda>ts::typ list. ts)"
wenzelm@12944
   124
  -- {* application of @{text id_subst} does not change list of type expressions *}
wenzelm@12944
   125
proof
wenzelm@12944
   126
  fix ts :: "typ list"
wenzelm@12944
   127
  show "$id_subst ts = ts"
wenzelm@12944
   128
    by (induct ts) (simp_all add: app_subst_list)
wenzelm@12944
   129
qed
wenzelm@12944
   130
wenzelm@12944
   131
lemma o_id_subst [simp]: "$s o id_subst = s"
wenzelm@12944
   132
  by (rule ext) (simp add: id_subst_def)
wenzelm@12944
   133
wenzelm@12944
   134
lemma dom_id_subst [simp]: "dom id_subst = {}"
nipkow@13890
   135
  by (simp add: dom_def id_subst_def)
wenzelm@12944
   136
wenzelm@12944
   137
lemma cod_id_subst [simp]: "cod id_subst = {}"
wenzelm@12944
   138
  by (simp add: cod_def)
wenzelm@12944
   139
wenzelm@12944
   140
lemma free_tv_id_subst [simp]: "free_tv id_subst = {}"
wenzelm@12944
   141
  by (simp add: free_tv_subst)
wenzelm@12944
   142
wenzelm@12944
   143
wenzelm@12944
   144
lemma cod_app_subst [simp]:
wenzelm@12944
   145
  assumes free: "v \<in> free_tv (s n)"
wenzelm@12944
   146
    and neq: "v \<noteq> n"
wenzelm@12944
   147
  shows "v \<in> cod s"
wenzelm@12944
   148
proof -
wenzelm@12944
   149
  have "s n \<noteq> TVar n"
wenzelm@12944
   150
  proof
wenzelm@12944
   151
    assume "s n = TVar n"
wenzelm@12944
   152
    with free have "v = n" by simp
wenzelm@12944
   153
    with neq show False ..
wenzelm@12944
   154
  qed
wenzelm@12944
   155
  with free show ?thesis
wenzelm@12944
   156
    by (auto simp add: dom_def cod_def)
wenzelm@12944
   157
qed
wenzelm@12944
   158
wenzelm@12944
   159
lemma subst_comp_te: "$g ($f t :: typ) = $(\<lambda>x. $g (f x)) t"
wenzelm@12944
   160
  -- {* composition of substitutions *}
wenzelm@12944
   161
  by (induct t) simp_all
wenzelm@12944
   162
wenzelm@12944
   163
lemma subst_comp_tel: "$g ($f ts :: typ list) = $(\<lambda>x. $g (f x)) ts"
wenzelm@12944
   164
  by (induct ts) (simp_all add: app_subst_list subst_comp_te)
wenzelm@12944
   165
wenzelm@12944
   166
wenzelm@12944
   167
lemma app_subst_Nil [simp]: "$s [] = []"
wenzelm@12944
   168
  by (simp add: app_subst_list)
wenzelm@12944
   169
wenzelm@12944
   170
lemma app_subst_Cons [simp]: "$s (t # ts) = ($s t) # ($s ts)"
wenzelm@12944
   171
  by (simp add: app_subst_list)
wenzelm@12944
   172
wenzelm@12944
   173
lemma new_tv_TVar [simp]: "new_tv n (TVar m) = (m < n)"
wenzelm@12944
   174
  by (simp add: new_tv_def)
wenzelm@12944
   175
wenzelm@12944
   176
lemma new_tv_Fun [simp]:
wenzelm@12944
   177
  "new_tv n (t1 -> t2) = (new_tv n t1 \<and> new_tv n t2)"
wenzelm@12944
   178
  by (auto simp add: new_tv_def)
wenzelm@12944
   179
wenzelm@12944
   180
lemma new_tv_Nil [simp]: "new_tv n []"
wenzelm@12944
   181
  by (simp add: new_tv_def)
wenzelm@12944
   182
wenzelm@12944
   183
lemma new_tv_Cons [simp]: "new_tv n (t # ts) = (new_tv n t \<and> new_tv n ts)"
wenzelm@12944
   184
  by (auto simp add: new_tv_def)
wenzelm@12944
   185
wenzelm@12944
   186
lemma new_tv_id_subst [simp]: "new_tv n id_subst"
wenzelm@12944
   187
  by (simp add: id_subst_def new_tv_def free_tv_subst dom_def cod_def)
wenzelm@12944
   188
wenzelm@12944
   189
lemma new_tv_subst:
wenzelm@12944
   190
  "new_tv n s =
wenzelm@12944
   191
    ((\<forall>m. n \<le> m \<longrightarrow> s m = TVar m) \<and>
wenzelm@12944
   192
     (\<forall>l. l < n \<longrightarrow> new_tv n (s l)))"
wenzelm@12944
   193
  apply (unfold new_tv_def)
wenzelm@12944
   194
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   195
  -- {* @{text \<Longrightarrow>} *}
wenzelm@12944
   196
    apply (tactic {* fast_tac (HOL_cs addDs [leD] addss (simpset()
wenzelm@12944
   197
      addsimps [thm "free_tv_subst", thm "dom_def"])) 1 *})
wenzelm@12944
   198
   apply (subgoal_tac "m \<in> cod s \<or> s l = TVar l")
wenzelm@12944
   199
    apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   200
     apply (tactic {* fast_tac (HOL_cs addDs [UnI2] addss (simpset()
wenzelm@12944
   201
       addsimps [thm "free_tv_subst"])) 1 *})
wenzelm@12944
   202
    apply (drule_tac P = "\<lambda>x. m \<in> free_tv x" in subst, assumption)
wenzelm@12944
   203
    apply simp
wenzelm@12944
   204
   apply (tactic {* fast_tac (set_cs addss (simpset()
wenzelm@12944
   205
     addsimps [thm "free_tv_subst", thm "cod_def", thm "dom_def"])) 1 *})
wenzelm@12944
   206
  -- {* @{text \<Longleftarrow>} *}
wenzelm@12944
   207
  apply (unfold free_tv_subst cod_def dom_def)
wenzelm@12944
   208
  apply (tactic "safe_tac set_cs")
wenzelm@12944
   209
   apply (cut_tac m = m and n = n in less_linear)
wenzelm@12944
   210
   apply (tactic "fast_tac (HOL_cs addSIs [less_or_eq_imp_le]) 1")
wenzelm@12944
   211
  apply (cut_tac m = ma and n = n in less_linear)
wenzelm@12944
   212
  apply (fast intro!: less_or_eq_imp_le)
wenzelm@12944
   213
  done
wenzelm@12944
   214
wenzelm@12944
   215
lemma new_tv_list: "new_tv n x = (\<forall>y \<in> set x. new_tv n y)"
wenzelm@12944
   216
  by (induct x) simp_all
wenzelm@12944
   217
wenzelm@12944
   218
lemma subst_te_new_tv [simp]:
wenzelm@12944
   219
  "new_tv n (t::typ) \<longrightarrow> $(\<lambda>x. if x = n then t' else s x) t = $s t"
wenzelm@12944
   220
  -- {* substitution affects only variables occurring freely *}
wenzelm@12944
   221
  by (induct t) simp_all
wenzelm@12944
   222
wenzelm@12944
   223
lemma subst_tel_new_tv [simp]:
wenzelm@12944
   224
  "new_tv n (ts::typ list) \<longrightarrow> $(\<lambda>x. if x = n then t else s x) ts = $s ts"
wenzelm@12944
   225
  by (induct ts) simp_all
wenzelm@12944
   226
wenzelm@12944
   227
lemma new_tv_le: "n \<le> m \<Longrightarrow> new_tv n (t::typ) \<Longrightarrow> new_tv m t"
wenzelm@12944
   228
  -- {* all greater variables are also new *}
wenzelm@12944
   229
proof (induct t)
wenzelm@12944
   230
  case (TVar n)
wenzelm@12944
   231
  thus ?case by (auto intro: less_le_trans)
wenzelm@12944
   232
next
wenzelm@12944
   233
  case TFun
wenzelm@12944
   234
  thus ?case by simp
wenzelm@12944
   235
qed
wenzelm@12944
   236
wenzelm@12944
   237
lemma [simp]: "new_tv n t \<Longrightarrow> new_tv (Suc n) (t::typ)"
wenzelm@12944
   238
  by (rule lessI [THEN less_imp_le [THEN new_tv_le]])
wenzelm@12944
   239
wenzelm@12944
   240
lemma new_tv_list_le:
wenzelm@12944
   241
  "n \<le> m \<Longrightarrow> new_tv n (ts::typ list) \<Longrightarrow> new_tv m ts"
wenzelm@12944
   242
proof (induct ts)
wenzelm@12944
   243
  case Nil
wenzelm@12944
   244
  thus ?case by simp
wenzelm@12944
   245
next
wenzelm@12944
   246
  case Cons
wenzelm@12944
   247
  thus ?case by (auto intro: new_tv_le)
wenzelm@12944
   248
qed
wenzelm@12944
   249
wenzelm@12944
   250
lemma [simp]: "new_tv n ts \<Longrightarrow> new_tv (Suc n) (ts::typ list)"
wenzelm@12944
   251
  by (rule lessI [THEN less_imp_le [THEN new_tv_list_le]])
wenzelm@12944
   252
wenzelm@12944
   253
lemma new_tv_subst_le: "n \<le> m \<Longrightarrow> new_tv n (s::subst) \<Longrightarrow> new_tv m s"
wenzelm@12944
   254
  apply (simp add: new_tv_subst)
wenzelm@12944
   255
  apply clarify
wenzelm@12944
   256
  apply (rule_tac P = "l < n" and Q = "n <= l" in disjE)
wenzelm@12944
   257
    apply clarify
wenzelm@12944
   258
    apply (simp_all add: new_tv_le)
wenzelm@12944
   259
  done
wenzelm@12944
   260
wenzelm@12944
   261
lemma [simp]: "new_tv n s \<Longrightarrow> new_tv (Suc n) (s::subst)"
wenzelm@12944
   262
  by (rule lessI [THEN less_imp_le [THEN new_tv_subst_le]])
wenzelm@12944
   263
wenzelm@12944
   264
lemma new_tv_subst_var:
wenzelm@12944
   265
    "n < m \<Longrightarrow> new_tv m (s::subst) \<Longrightarrow> new_tv m (s n)"
wenzelm@12944
   266
  -- {* @{text new_tv} property remains if a substitution is applied *}
wenzelm@12944
   267
  by (simp add: new_tv_subst)
wenzelm@12944
   268
wenzelm@12944
   269
lemma new_tv_subst_te [simp]:
wenzelm@12944
   270
    "new_tv n s \<Longrightarrow> new_tv n (t::typ) \<Longrightarrow> new_tv n ($s t)"
wenzelm@12944
   271
  by (induct t) (auto simp add: new_tv_subst)
wenzelm@12944
   272
wenzelm@12944
   273
lemma new_tv_subst_tel [simp]:
wenzelm@12944
   274
    "new_tv n s \<Longrightarrow> new_tv n (ts::typ list) \<Longrightarrow> new_tv n ($s ts)"
wenzelm@12944
   275
  by (induct ts) (fastsimp simp add: new_tv_subst)+
wenzelm@12944
   276
wenzelm@12944
   277
lemma new_tv_Suc_list: "new_tv n ts --> new_tv (Suc n) (TVar n # ts)"
wenzelm@12944
   278
  -- {* auxilliary lemma *}
wenzelm@12944
   279
  by (simp add: new_tv_list)
wenzelm@12944
   280
wenzelm@12944
   281
lemma new_tv_subst_comp_1 [simp]:
wenzelm@12944
   282
    "new_tv n (s::subst) \<Longrightarrow> new_tv n r \<Longrightarrow> new_tv n ($r o s)"
wenzelm@12944
   283
  -- {* composition of substitutions preserves @{text new_tv} proposition *}
wenzelm@12944
   284
  by (simp add: new_tv_subst)
wenzelm@12944
   285
wenzelm@12944
   286
lemma new_tv_subst_comp_2 [simp]:
wenzelm@12944
   287
    "new_tv n (s::subst) \<Longrightarrow> new_tv n r \<Longrightarrow> new_tv n (\<lambda>v. $r (s v))"
wenzelm@12944
   288
  by (simp add: new_tv_subst)
wenzelm@12944
   289
wenzelm@12944
   290
lemma new_tv_not_free_tv [simp]: "new_tv n ts \<Longrightarrow> n \<notin> free_tv ts"
wenzelm@12944
   291
  -- {* new type variables do not occur freely in a type structure *}
wenzelm@12944
   292
  by (auto simp add: new_tv_def)
wenzelm@12944
   293
wenzelm@12944
   294
lemma ftv_mem_sub_ftv_list [simp]:
wenzelm@12944
   295
    "(t::typ) \<in> set ts \<Longrightarrow> free_tv t \<subseteq> free_tv ts"
wenzelm@12944
   296
  by (induct ts) auto
wenzelm@12944
   297
wenzelm@12944
   298
text {*
wenzelm@12944
   299
  If two substitutions yield the same result if applied to a type
wenzelm@12944
   300
  structure the substitutions coincide on the free type variables
wenzelm@12944
   301
  occurring in the type structure.
wenzelm@12944
   302
*}
wenzelm@12944
   303
wenzelm@12944
   304
lemma eq_subst_te_eq_free:
wenzelm@12944
   305
    "$s1 (t::typ) = $s2 t \<Longrightarrow> n \<in> free_tv t \<Longrightarrow> s1 n = s2 n"
wenzelm@12944
   306
  by (induct t) auto
wenzelm@12944
   307
wenzelm@12944
   308
lemma eq_free_eq_subst_te:
wenzelm@12944
   309
    "(\<forall>n. n \<in> free_tv t --> s1 n = s2 n) \<Longrightarrow> $s1 (t::typ) = $s2 t"
wenzelm@12944
   310
  by (induct t) auto
wenzelm@12944
   311
wenzelm@12944
   312
lemma eq_subst_tel_eq_free:
wenzelm@12944
   313
    "$s1 (ts::typ list) = $s2 ts \<Longrightarrow> n \<in> free_tv ts \<Longrightarrow> s1 n = s2 n"
wenzelm@12944
   314
  by (induct ts) (auto intro: eq_subst_te_eq_free)
wenzelm@12944
   315
wenzelm@12944
   316
lemma eq_free_eq_subst_tel:
wenzelm@12944
   317
    "(\<forall>n. n \<in> free_tv ts --> s1 n = s2 n) \<Longrightarrow> $s1 (ts::typ list) = $s2 ts"
wenzelm@12944
   318
  by (induct ts) (auto intro: eq_free_eq_subst_te)
wenzelm@12944
   319
wenzelm@12944
   320
text {*
wenzelm@12944
   321
  \medskip Some useful lemmas.
wenzelm@12944
   322
*}
wenzelm@12944
   323
wenzelm@12944
   324
lemma codD: "v \<in> cod s \<Longrightarrow> v \<in> free_tv s"
wenzelm@12944
   325
  by (simp add: free_tv_subst)
wenzelm@12944
   326
wenzelm@12944
   327
lemma not_free_impl_id: "x \<notin> free_tv s \<Longrightarrow> s x = TVar x"
wenzelm@12944
   328
  by (simp add: free_tv_subst dom_def)
wenzelm@12944
   329
wenzelm@12944
   330
lemma free_tv_le_new_tv: "new_tv n t \<Longrightarrow> m \<in> free_tv t \<Longrightarrow> m < n"
wenzelm@12944
   331
  by (unfold new_tv_def) fast
wenzelm@12944
   332
wenzelm@12944
   333
lemma free_tv_subst_var: "free_tv (s (v::nat)) \<le> insert v (cod s)"
wenzelm@12944
   334
  by (cases "v \<in> dom s") (auto simp add: cod_def dom_def)
wenzelm@12944
   335
wenzelm@12944
   336
lemma free_tv_app_subst_te: "free_tv ($s (t::typ)) \<subseteq> cod s \<union> free_tv t"
wenzelm@12944
   337
  by (induct t) (auto simp add: free_tv_subst_var)
wenzelm@12944
   338
wenzelm@12944
   339
lemma free_tv_app_subst_tel: "free_tv ($s (ts::typ list)) \<subseteq> cod s \<union> free_tv ts"
wenzelm@12944
   340
  apply (induct ts)
wenzelm@12944
   341
   apply simp
wenzelm@12944
   342
  apply (cut_tac free_tv_app_subst_te)
wenzelm@12944
   343
  apply fastsimp
wenzelm@12944
   344
  done
wenzelm@12944
   345
wenzelm@12944
   346
lemma free_tv_comp_subst:
wenzelm@12944
   347
    "free_tv (\<lambda>u::nat. $s1 (s2 u) :: typ) \<subseteq> free_tv s1 \<union> free_tv s2"
wenzelm@12944
   348
  apply (unfold free_tv_subst dom_def)
wenzelm@12944
   349
  apply (tactic {*
wenzelm@12944
   350
    fast_tac (set_cs addSDs [thm "free_tv_app_subst_te" RS subsetD,
wenzelm@12944
   351
    thm "free_tv_subst_var" RS subsetD]
wenzelm@12944
   352
    addss (simpset() delsimps bex_simps
wenzelm@12944
   353
    addsimps [thm "cod_def", thm "dom_def"])) 1 *})
wenzelm@12944
   354
  done
wenzelm@12944
   355
wenzelm@12944
   356
wenzelm@12944
   357
subsection {* Most general unifiers *}
wenzelm@12944
   358
wenzelm@12944
   359
consts
wenzelm@12944
   360
  mgu :: "typ \<Rightarrow> typ \<Rightarrow> subst maybe"
wenzelm@12944
   361
axioms
wenzelm@12944
   362
  mgu_eq [simp]: "mgu t1 t2 = Ok u \<Longrightarrow> $u t1 = $u t2"
wenzelm@12944
   363
  mgu_mg [simp]: "mgu t1 t2 = Ok u \<Longrightarrow> $s t1 = $s t2 \<Longrightarrow> \<exists>r. s = $r o u"
wenzelm@12944
   364
  mgu_Ok: "$s t1 = $s t2 \<Longrightarrow> \<exists>u. mgu t1 t2 = Ok u"
wenzelm@12944
   365
  mgu_free [simp]: "mgu t1 t2 = Ok u \<Longrightarrow> free_tv u \<subseteq> free_tv t1 \<union> free_tv t2"
wenzelm@12944
   366
wenzelm@12944
   367
lemma mgu_new: "mgu t1 t2 = Ok u \<Longrightarrow> new_tv n t1 \<Longrightarrow> new_tv n t2 \<Longrightarrow> new_tv n u"
wenzelm@12944
   368
  -- {* @{text mgu} does not introduce new type variables *}
wenzelm@12944
   369
  by (unfold new_tv_def) (blast dest: mgu_free)
wenzelm@12944
   370
wenzelm@12944
   371
wenzelm@12944
   372
section {* Mini-ML with type inference rules *}
wenzelm@12944
   373
wenzelm@12944
   374
datatype
wenzelm@12944
   375
  expr = Var nat | Abs expr | App expr expr
wenzelm@12944
   376
wenzelm@12944
   377
wenzelm@12944
   378
text {* Type inference rules. *}
wenzelm@12944
   379
wenzelm@12944
   380
consts
wenzelm@12944
   381
  has_type :: "(typ list \<times> expr \<times> typ) set"
wenzelm@12944
   382
wenzelm@12944
   383
syntax
wenzelm@12944
   384
  "_has_type" :: "typ list \<Rightarrow> expr \<Rightarrow> typ \<Rightarrow> bool"
wenzelm@12944
   385
    ("((_) |-/ (_) :: (_))" [60, 0, 60] 60)
wenzelm@12944
   386
translations
wenzelm@12944
   387
  "a |- e :: t" == "(a, e, t) \<in> has_type"
wenzelm@12944
   388
wenzelm@12944
   389
inductive has_type
wenzelm@12944
   390
  intros
wenzelm@12944
   391
    Var: "n < length a \<Longrightarrow> a |- Var n :: a ! n"
wenzelm@12944
   392
    Abs: "t1#a |- e :: t2 \<Longrightarrow> a |- Abs e :: t1 -> t2"
wenzelm@12944
   393
    App: "a |- e1 :: t2 -> t1 \<Longrightarrow> a |- e2 :: t2
wenzelm@12944
   394
      \<Longrightarrow> a |- App e1 e2 :: t1"
wenzelm@12944
   395
wenzelm@12944
   396
wenzelm@12944
   397
text {* Type assigment is closed wrt.\ substitution. *}
wenzelm@12944
   398
wenzelm@12944
   399
lemma has_type_subst_closed: "a |- e :: t ==> $s a |- e :: $s t"
wenzelm@12944
   400
proof -
wenzelm@12944
   401
  assume "a |- e :: t"
wenzelm@12944
   402
  thus ?thesis (is "?P a e t")
wenzelm@12944
   403
  proof induct
wenzelm@12944
   404
    case (Var a n)
wenzelm@12944
   405
    hence "n < length (map ($ s) a)" by simp
wenzelm@12944
   406
    hence "map ($ s) a |- Var n :: map ($ s) a ! n"
wenzelm@12944
   407
      by (rule has_type.Var)
wenzelm@12944
   408
    also have "map ($ s) a ! n = $ s (a ! n)"
wenzelm@12944
   409
      by (rule nth_map)
wenzelm@12944
   410
    also have "map ($ s) a = $ s a"
wenzelm@12944
   411
      by (simp only: app_subst_list)
wenzelm@12944
   412
    finally show "?P a (Var n) (a ! n)" .
wenzelm@12944
   413
  next
wenzelm@12944
   414
    case (Abs a e t1 t2)
wenzelm@12944
   415
    hence "$ s t1 # map ($ s) a |- e :: $ s t2"
wenzelm@12944
   416
      by (simp add: app_subst_list)
wenzelm@12944
   417
    hence "map ($ s) a |- Abs e :: $ s t1 -> $ s t2"
wenzelm@12944
   418
      by (rule has_type.Abs)
wenzelm@12944
   419
    thus "?P a (Abs e) (t1 -> t2)"
wenzelm@12944
   420
      by (simp add: app_subst_list)
wenzelm@12944
   421
  next
wenzelm@12944
   422
    case App
wenzelm@12944
   423
    thus ?case by (simp add: has_type.App)
wenzelm@12944
   424
  qed
wenzelm@12944
   425
qed
wenzelm@12944
   426
wenzelm@12944
   427
wenzelm@12961
   428
section {* Correctness and completeness of the type inference algorithm W *}
wenzelm@12944
   429
wenzelm@12944
   430
consts
wenzelm@12944
   431
  W :: "expr \<Rightarrow> typ list \<Rightarrow> nat \<Rightarrow> (subst \<times> typ \<times> nat) maybe"  ("\<W>")
wenzelm@12944
   432
wenzelm@12944
   433
primrec
wenzelm@12944
   434
  "\<W> (Var i) a n =
wenzelm@12944
   435
    (if i < length a then Ok (id_subst, a ! i, n) else Fail)"
wenzelm@12944
   436
  "\<W> (Abs e) a n =
wenzelm@12944
   437
    ((s, t, m) := \<W> e (TVar n # a) (Suc n);
wenzelm@12944
   438
     Ok (s, (s n) -> t, m))"
wenzelm@12944
   439
  "\<W> (App e1 e2) a n =
wenzelm@12944
   440
    ((s1, t1, m1) := \<W> e1 a n;
wenzelm@12944
   441
     (s2, t2, m2) := \<W> e2 ($s1 a) m1;
wenzelm@12944
   442
     u := mgu ($ s2 t1) (t2 -> TVar m2);
wenzelm@12944
   443
     Ok ($u o $s2 o s1, $u (TVar m2), Suc m2))"
wenzelm@12944
   444
wenzelm@12944
   445
theorem W_correct: "!!a s t m n. Ok (s, t, m) = \<W> e a n ==> $s a |- e :: t"
wenzelm@12944
   446
  (is "PROP ?P e")
wenzelm@12944
   447
proof (induct e)
wenzelm@12944
   448
  fix a s t m n
wenzelm@12944
   449
  {
wenzelm@12944
   450
    fix i
wenzelm@12944
   451
    assume "Ok (s, t, m) = \<W> (Var i) a n"
wenzelm@12944
   452
    thus "$s a |- Var i :: t" by (simp add: has_type.Var split: if_splits)
wenzelm@12944
   453
  next
wenzelm@12944
   454
    fix e assume hyp: "PROP ?P e"
wenzelm@12944
   455
    assume "Ok (s, t, m) = \<W> (Abs e) a n"
wenzelm@12944
   456
    then obtain t' where "t = s n -> t'"
wenzelm@12944
   457
        and "Ok (s, t', m) = \<W> e (TVar n # a) (Suc n)"
wenzelm@12944
   458
      by (auto split: bind_splits)
wenzelm@12944
   459
    with hyp show "$s a |- Abs e :: t"
wenzelm@12944
   460
      by (force intro: has_type.Abs)
wenzelm@12944
   461
  next
wenzelm@12944
   462
    fix e1 e2 assume hyp1: "PROP ?P e1" and hyp2: "PROP ?P e2"
wenzelm@12944
   463
    assume "Ok (s, t, m) = \<W> (App e1 e2) a n"
wenzelm@12944
   464
    then obtain s1 t1 n1 s2 t2 n2 u where
wenzelm@12944
   465
          s: "s = $u o $s2 o s1"
wenzelm@12944
   466
        and t: "t = u n2"
wenzelm@12944
   467
        and mgu_ok: "mgu ($s2 t1) (t2 -> TVar n2) = Ok u"
wenzelm@12944
   468
        and W1_ok: "Ok (s1, t1, n1) = \<W> e1 a n"
wenzelm@12944
   469
        and W2_ok: "Ok (s2, t2, n2) = \<W> e2 ($s1 a) n1"
wenzelm@12944
   470
      by (auto split: bind_splits simp: that)
wenzelm@12944
   471
    show "$s a |- App e1 e2 :: t"
wenzelm@12944
   472
    proof (rule has_type.App)
wenzelm@12944
   473
      from s have s': "$u ($s2 ($s1 a)) = $s a"
wenzelm@12944
   474
        by (simp add: subst_comp_tel o_def)
wenzelm@12944
   475
      show "$s a |- e1 :: $u t2 -> t"
wenzelm@12944
   476
      proof -
wenzelm@12944
   477
        from W1_ok have "$s1 a |- e1 :: t1" by (rule hyp1)
wenzelm@12944
   478
        hence "$u ($s2 ($s1 a)) |- e1 :: $u ($s2 t1)"
wenzelm@12944
   479
          by (intro has_type_subst_closed)
wenzelm@12944
   480
        with s' t mgu_ok show ?thesis by simp
wenzelm@12944
   481
      qed
wenzelm@12944
   482
      show "$s a |- e2 :: $u t2"
wenzelm@12944
   483
      proof -
wenzelm@12944
   484
        from W2_ok have "$s2 ($s1 a) |- e2 :: t2" by (rule hyp2)
wenzelm@12944
   485
        hence "$u ($s2 ($s1 a)) |- e2 :: $u t2"
wenzelm@12944
   486
          by (rule has_type_subst_closed)
wenzelm@12944
   487
        with s' show ?thesis by simp
wenzelm@12944
   488
      qed
wenzelm@12944
   489
    qed
wenzelm@12944
   490
  }
wenzelm@12944
   491
qed
wenzelm@12944
   492
wenzelm@12944
   493
wenzelm@12944
   494
inductive_cases has_type_casesE:
wenzelm@12944
   495
  "s |- Var n :: t"
wenzelm@12944
   496
  "s |- Abs e :: t"
wenzelm@12944
   497
  "s |- App e1 e2 ::t"
wenzelm@12944
   498
wenzelm@12944
   499
wenzelm@12944
   500
lemmas [simp] = Suc_le_lessD
wenzelm@12944
   501
  and [simp del] = less_imp_le ex_simps all_simps
wenzelm@12944
   502
wenzelm@12944
   503
lemma W_var_ge [simp]: "!!a n s t m. \<W> e a n = Ok (s, t, m) \<Longrightarrow> n \<le> m"
wenzelm@12944
   504
  -- {* the resulting type variable is always greater or equal than the given one *}
wenzelm@12944
   505
  apply (atomize (full))
wenzelm@12944
   506
  apply (induct e)
wenzelm@12944
   507
    txt {* case @{text "Var n"} *}
wenzelm@12944
   508
    apply clarsimp
wenzelm@12944
   509
   txt {* case @{text "Abs e"} *}
wenzelm@12944
   510
   apply (simp split add: split_bind)
wenzelm@12944
   511
   apply (fast dest: Suc_leD)
wenzelm@12944
   512
  txt {* case @{text "App e1 e2"} *}
wenzelm@12944
   513
  apply (simp (no_asm) split add: split_bind)
wenzelm@12944
   514
  apply (intro strip)
wenzelm@12944
   515
  apply (rename_tac s t na sa ta nb sb)
wenzelm@12944
   516
  apply (erule_tac x = a in allE)
wenzelm@12944
   517
  apply (erule_tac x = n in allE)
wenzelm@12944
   518
  apply (erule_tac x = "$s a" in allE)
wenzelm@12944
   519
  apply (erule_tac x = s in allE)
wenzelm@12944
   520
  apply (erule_tac x = t in allE)
wenzelm@12944
   521
  apply (erule_tac x = na in allE)
wenzelm@12944
   522
  apply (erule_tac x = na in allE)
wenzelm@12944
   523
  apply (simp add: eq_sym_conv)
wenzelm@12944
   524
  done
wenzelm@12944
   525
wenzelm@12944
   526
lemma W_var_geD: "Ok (s, t, m) = \<W> e a n \<Longrightarrow> n \<le> m"
wenzelm@12944
   527
  by (simp add: eq_sym_conv)
wenzelm@12944
   528
wenzelm@12944
   529
lemma new_tv_W: "!!n a s t m.
wenzelm@12944
   530
  new_tv n a \<Longrightarrow> \<W> e a n = Ok (s, t, m) \<Longrightarrow> new_tv m s & new_tv m t"
wenzelm@12944
   531
  -- {* resulting type variable is new *}
wenzelm@12944
   532
  apply (atomize (full))
wenzelm@12944
   533
  apply (induct e)
wenzelm@12944
   534
    txt {* case @{text "Var n"} *}
wenzelm@12944
   535
    apply clarsimp
wenzelm@12944
   536
    apply (force elim: list_ball_nth simp add: id_subst_def new_tv_list new_tv_subst)
wenzelm@12944
   537
   txt {* case @{text "Abs e"} *}
wenzelm@12944
   538
   apply (simp (no_asm) add: new_tv_subst new_tv_Suc_list split add: split_bind)
wenzelm@12944
   539
   apply (intro strip)
wenzelm@12944
   540
   apply (erule_tac x = "Suc n" in allE)
wenzelm@12944
   541
   apply (erule_tac x = "TVar n # a" in allE)
wenzelm@12944
   542
   apply (fastsimp simp add: new_tv_subst new_tv_Suc_list)
wenzelm@12944
   543
  txt {* case @{text "App e1 e2"} *}
wenzelm@12944
   544
  apply (simp (no_asm) split add: split_bind)
wenzelm@12944
   545
  apply (intro strip)
wenzelm@12944
   546
  apply (rename_tac s t na sa ta nb sb)
wenzelm@12944
   547
  apply (erule_tac x = n in allE)
wenzelm@12944
   548
  apply (erule_tac x = a in allE)
wenzelm@12944
   549
  apply (erule_tac x = s in allE)
wenzelm@12944
   550
  apply (erule_tac x = t in allE)
wenzelm@12944
   551
  apply (erule_tac x = na in allE)
wenzelm@12944
   552
  apply (erule_tac x = na in allE)
wenzelm@12944
   553
  apply (simp add: eq_sym_conv)
wenzelm@12944
   554
  apply (erule_tac x = "$s a" in allE)
wenzelm@12944
   555
  apply (erule_tac x = sa in allE)
wenzelm@12944
   556
  apply (erule_tac x = ta in allE)
wenzelm@12944
   557
  apply (erule_tac x = nb in allE)
wenzelm@12944
   558
  apply (simp add: o_def rotate_Ok)
wenzelm@12944
   559
  apply (rule conjI)
wenzelm@12944
   560
   apply (rule new_tv_subst_comp_2)
wenzelm@12944
   561
    apply (rule new_tv_subst_comp_2)
wenzelm@12944
   562
     apply (rule lessI [THEN less_imp_le, THEN new_tv_subst_le])
wenzelm@12944
   563
     apply (rule_tac n = na in new_tv_subst_le)
wenzelm@12944
   564
      apply (simp add: rotate_Ok)
wenzelm@12944
   565
     apply (simp (no_asm_simp))
wenzelm@12944
   566
    apply (fast dest: W_var_geD intro: new_tv_list_le new_tv_subst_tel
wenzelm@12944
   567
      lessI [THEN less_imp_le, THEN new_tv_subst_le])
wenzelm@12944
   568
   apply (erule sym [THEN mgu_new])
wenzelm@12944
   569
    apply (best dest: W_var_geD intro: new_tv_subst_te new_tv_list_le new_tv_subst_tel
wenzelm@12944
   570
      lessI [THEN less_imp_le, THEN new_tv_le] lessI [THEN less_imp_le, THEN new_tv_subst_le]
wenzelm@12944
   571
      new_tv_le)
wenzelm@12944
   572
   apply (tactic {* fast_tac (HOL_cs addDs [thm "W_var_geD"]
wenzelm@12944
   573
     addIs [thm "new_tv_list_le", thm "new_tv_subst_tel", thm "new_tv_le"]
wenzelm@12944
   574
     addss (simpset())) 1 *})
wenzelm@12944
   575
  apply (rule lessI [THEN new_tv_subst_var])
wenzelm@12944
   576
  apply (erule sym [THEN mgu_new])
wenzelm@12944
   577
    apply (bestsimp intro!: lessI [THEN less_imp_le, THEN new_tv_le] new_tv_subst_te
wenzelm@12944
   578
      dest!: W_var_geD intro: new_tv_list_le new_tv_subst_tel
wenzelm@12944
   579
        lessI [THEN less_imp_le, THEN new_tv_subst_le] new_tv_le)
wenzelm@12944
   580
  apply (tactic {* fast_tac (HOL_cs addDs [thm "W_var_geD"]
wenzelm@12944
   581
    addIs [thm "new_tv_list_le", thm "new_tv_subst_tel", thm "new_tv_le"]
wenzelm@12944
   582
    addss (simpset())) 1 *})
wenzelm@12944
   583
  done
wenzelm@12944
   584
wenzelm@12944
   585
lemma free_tv_W: "!!n a s t m v. \<W> e a n = Ok (s, t, m) \<Longrightarrow>
wenzelm@12944
   586
    (v \<in> free_tv s \<or> v \<in> free_tv t) \<Longrightarrow> v < n \<Longrightarrow> v \<in> free_tv a"
wenzelm@12944
   587
  apply (atomize (full))
wenzelm@12944
   588
  apply (induct e)
wenzelm@12944
   589
    txt {* case @{text "Var n"} *}
wenzelm@12944
   590
    apply clarsimp
wenzelm@12944
   591
    apply (tactic {* fast_tac (HOL_cs addIs [nth_mem, subsetD, thm "ftv_mem_sub_ftv_list"]) 1 *})
wenzelm@12944
   592
   txt {* case @{text "Abs e"} *}
wenzelm@12944
   593
   apply (simp add: free_tv_subst split add: split_bind)
wenzelm@12944
   594
   apply (intro strip)
wenzelm@12944
   595
   apply (rename_tac s t n1 v)
wenzelm@12944
   596
   apply (erule_tac x = "Suc n" in allE)
wenzelm@12944
   597
   apply (erule_tac x = "TVar n # a" in allE)
wenzelm@12944
   598
   apply (erule_tac x = s in allE)
wenzelm@12944
   599
   apply (erule_tac x = t in allE)
wenzelm@12944
   600
   apply (erule_tac x = n1 in allE)
wenzelm@12944
   601
   apply (erule_tac x = v in allE)
wenzelm@12944
   602
   apply (force elim!: allE intro: cod_app_subst)
wenzelm@12944
   603
  txt {* case @{text "App e1 e2"} *}
wenzelm@12944
   604
  apply (simp (no_asm) split add: split_bind)
wenzelm@12944
   605
  apply (intro strip)
wenzelm@12944
   606
  apply (rename_tac s t n1 s1 t1 n2 s3 v)
wenzelm@12944
   607
  apply (erule_tac x = n in allE)
wenzelm@12944
   608
  apply (erule_tac x = a in allE)
wenzelm@12944
   609
  apply (erule_tac x = s in allE)
wenzelm@12944
   610
  apply (erule_tac x = t in allE)
wenzelm@12944
   611
  apply (erule_tac x = n1 in allE)
wenzelm@12944
   612
  apply (erule_tac x = n1 in allE)
wenzelm@12944
   613
  apply (erule_tac x = v in allE)
wenzelm@12944
   614
  txt {* second case *}
wenzelm@12944
   615
  apply (erule_tac x = "$ s a" in allE)
wenzelm@12944
   616
  apply (erule_tac x = s1 in allE)
wenzelm@12944
   617
  apply (erule_tac x = t1 in allE)
wenzelm@12944
   618
  apply (erule_tac x = n2 in allE)
wenzelm@12944
   619
  apply (erule_tac x = v in allE)
wenzelm@12944
   620
  apply (tactic "safe_tac (empty_cs addSIs [conjI, impI] addSEs [conjE])")
wenzelm@12944
   621
   apply (simp add: rotate_Ok o_def)
wenzelm@12944
   622
   apply (drule W_var_geD)
wenzelm@12944
   623
   apply (drule W_var_geD)
wenzelm@12944
   624
   apply (frule less_le_trans, assumption)
wenzelm@12944
   625
   apply (fastsimp dest: free_tv_comp_subst [THEN subsetD] sym [THEN mgu_free] codD
wenzelm@12944
   626
     free_tv_app_subst_te [THEN subsetD] free_tv_app_subst_tel [THEN subsetD] subsetD elim: UnE)
wenzelm@12944
   627
  apply simp
wenzelm@12944
   628
  apply (drule sym [THEN W_var_geD])
wenzelm@12944
   629
  apply (drule sym [THEN W_var_geD])
wenzelm@12944
   630
  apply (frule less_le_trans, assumption)
wenzelm@12944
   631
  apply (tactic {* fast_tac (HOL_cs addDs [thm "mgu_free", thm "codD",
wenzelm@12944
   632
    thm "free_tv_subst_var" RS subsetD,
wenzelm@12944
   633
    thm "free_tv_app_subst_te" RS subsetD,
wenzelm@12944
   634
    thm "free_tv_app_subst_tel" RS subsetD, less_le_trans, subsetD]
wenzelm@12944
   635
    addSEs [UnE] addss (simpset() setSolver unsafe_solver)) 1 *})
wenzelm@12944
   636
      -- {* builtin arithmetic in simpset messes things up *}
wenzelm@12944
   637
  done
wenzelm@12944
   638
wenzelm@12944
   639
text {*
wenzelm@12944
   640
  \medskip Completeness of @{text \<W>} wrt.\ @{text has_type}.
wenzelm@12944
   641
*}
wenzelm@12944
   642
wenzelm@12944
   643
lemma W_complete_aux: "!!s' a t' n. $s' a |- e :: t' \<Longrightarrow> new_tv n a \<Longrightarrow>
wenzelm@12944
   644
    (\<exists>s t. (\<exists>m. \<W> e a n = Ok (s, t, m)) \<and> (\<exists>r. $s' a = $r ($s a) \<and> t' = $r t))"
wenzelm@12944
   645
  apply (atomize (full))
wenzelm@12944
   646
  apply (induct e)
wenzelm@12944
   647
    txt {* case @{text "Var n"} *}
wenzelm@12944
   648
    apply (intro strip)
wenzelm@12944
   649
    apply (simp (no_asm) cong add: conj_cong)
wenzelm@12944
   650
    apply (erule has_type_casesE)
wenzelm@12944
   651
    apply (simp add: eq_sym_conv app_subst_list)
wenzelm@12944
   652
    apply (rule_tac x = s' in exI)
wenzelm@12944
   653
    apply simp
wenzelm@12944
   654
   txt {* case @{text "Abs e"} *}
wenzelm@12944
   655
   apply (intro strip)
wenzelm@12944
   656
   apply (erule has_type_casesE)
wenzelm@12944
   657
   apply (erule_tac x = "\<lambda>x. if x = n then t1 else (s' x)" in allE)
wenzelm@12944
   658
   apply (erule_tac x = "TVar n # a" in allE)
wenzelm@12944
   659
   apply (erule_tac x = t2 in allE)
wenzelm@12944
   660
   apply (erule_tac x = "Suc n" in allE)
wenzelm@12944
   661
   apply (fastsimp cong add: conj_cong split add: split_bind)
wenzelm@12944
   662
  txt {* case @{text "App e1 e2"} *}
wenzelm@12944
   663
  apply (intro strip)
wenzelm@12944
   664
  apply (erule has_type_casesE)
wenzelm@12944
   665
  apply (erule_tac x = s' in allE)
wenzelm@12944
   666
  apply (erule_tac x = a in allE)
wenzelm@12944
   667
  apply (erule_tac x = "t2 -> t'" in allE)
wenzelm@12944
   668
  apply (erule_tac x = n in allE)
wenzelm@12944
   669
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   670
  apply (erule_tac x = r in allE)
wenzelm@12944
   671
  apply (erule_tac x = "$s a" in allE)
wenzelm@12944
   672
  apply (erule_tac x = t2 in allE)
wenzelm@12944
   673
  apply (erule_tac x = m in allE)
wenzelm@12944
   674
  apply simp
wenzelm@12944
   675
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   676
   apply (tactic {* fast_tac (HOL_cs addIs [sym RS thm "W_var_geD",
wenzelm@12944
   677
     thm "new_tv_W" RS conjunct1, thm "new_tv_list_le", thm "new_tv_subst_tel"]) 1 *})
wenzelm@12944
   678
  apply (subgoal_tac
wenzelm@12944
   679
    "$(\<lambda>x. if x = ma then t' else (if x \<in> free_tv t - free_tv sa then r x
wenzelm@12944
   680
      else ra x)) ($ sa t) =
wenzelm@12944
   681
    $(\<lambda>x. if x = ma then t' else (if x \<in> free_tv t - free_tv sa then r x
wenzelm@12944
   682
      else ra x)) (ta -> (TVar ma))")
wenzelm@12944
   683
   apply (rule_tac [2] t = "$(\<lambda>x. if x = ma then t'
wenzelm@12944
   684
     else (if x \<in> (free_tv t - free_tv sa) then r x else ra x)) ($sa t)" and
wenzelm@12944
   685
     s = "($ ra ta) -> t'" in ssubst)
wenzelm@12944
   686
    prefer 2
wenzelm@12944
   687
    apply (simp add: subst_comp_te)
wenzelm@12944
   688
    apply (rule eq_free_eq_subst_te)
wenzelm@12944
   689
    apply (intro strip)
wenzelm@12944
   690
    apply (subgoal_tac "na \<noteq> ma")
wenzelm@12944
   691
     prefer 2
wenzelm@12944
   692
     apply (fast dest: new_tv_W sym [THEN W_var_geD] new_tv_not_free_tv new_tv_le)
wenzelm@12944
   693
    apply (case_tac "na \<in> free_tv sa")
wenzelm@12944
   694
     txt {* @{text "na \<notin> free_tv sa"} *}
wenzelm@12944
   695
     prefer 2
wenzelm@12944
   696
     apply (frule not_free_impl_id)
wenzelm@12944
   697
     apply simp
wenzelm@12944
   698
    txt {* @{text "na \<in> free_tv sa"} *}
berghofe@13601
   699
    apply (drule_tac ts1 = "$s a" and r = "$ r ($ s a)" in subst_comp_tel [THEN [2] trans])
wenzelm@12944
   700
    apply (drule_tac eq_subst_tel_eq_free)
wenzelm@12944
   701
     apply (fast intro: free_tv_W free_tv_le_new_tv dest: new_tv_W)
wenzelm@12944
   702
    apply simp
wenzelm@12944
   703
    apply (case_tac "na \<in> dom sa")
wenzelm@12944
   704
     prefer 2
wenzelm@12944
   705
     txt {* @{text "na \<noteq> dom sa"} *}
wenzelm@12944
   706
     apply (simp add: dom_def)
wenzelm@12944
   707
    txt {* @{text "na \<in> dom sa"} *}
wenzelm@12944
   708
    apply (rule eq_free_eq_subst_te)
wenzelm@12944
   709
    apply (intro strip)
wenzelm@12944
   710
    apply (subgoal_tac "nb \<noteq> ma")
wenzelm@12944
   711
     prefer 2
wenzelm@12944
   712
     apply (frule new_tv_W, assumption)
wenzelm@12944
   713
     apply (erule conjE)
wenzelm@12944
   714
     apply (drule new_tv_subst_tel)
wenzelm@12944
   715
      apply (fast intro: new_tv_list_le dest: sym [THEN W_var_geD])
wenzelm@12944
   716
     apply (fastsimp dest: new_tv_W new_tv_not_free_tv simp add: cod_def free_tv_subst)
wenzelm@12944
   717
    apply (fastsimp simp add: cod_def free_tv_subst)
wenzelm@12944
   718
   prefer 2
wenzelm@12944
   719
   apply (simp (no_asm))
wenzelm@12944
   720
   apply (rule eq_free_eq_subst_te)
wenzelm@12944
   721
   apply (intro strip)
wenzelm@12944
   722
   apply (subgoal_tac "na \<noteq> ma")
wenzelm@12944
   723
    prefer 2
wenzelm@12944
   724
    apply (frule new_tv_W, assumption)
wenzelm@12944
   725
    apply (erule conjE)
wenzelm@12944
   726
    apply (drule sym [THEN W_var_geD])
wenzelm@12944
   727
    apply (fast dest: new_tv_list_le new_tv_subst_tel new_tv_W new_tv_not_free_tv)
wenzelm@12944
   728
   apply (case_tac "na \<in> free_tv t - free_tv sa")
wenzelm@12944
   729
    prefer 2
wenzelm@12944
   730
    txt {* case @{text "na \<notin> free_tv t - free_tv sa"} *}
wenzelm@12944
   731
    apply simp
wenzelm@12944
   732
    defer
wenzelm@12944
   733
    txt {* case @{text "na \<in> free_tv t - free_tv sa"} *}
wenzelm@12944
   734
    apply simp
berghofe@13601
   735
    apply (drule_tac ts1 = "$s a" and r = "$ r ($ s a)" in subst_comp_tel [THEN [2] trans])
wenzelm@12944
   736
    apply (drule eq_subst_tel_eq_free)
wenzelm@12944
   737
     apply (fast intro: free_tv_W free_tv_le_new_tv dest: new_tv_W)
wenzelm@12944
   738
    apply (simp add: free_tv_subst dom_def)
wenzelm@12944
   739
   prefer 2 apply fast
wenzelm@12944
   740
  apply (simp (no_asm_simp) split add: split_bind)
wenzelm@12944
   741
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   742
   apply (drule mgu_Ok)
wenzelm@12944
   743
   apply fastsimp
wenzelm@12944
   744
  apply (drule mgu_mg, assumption)
wenzelm@12944
   745
  apply (erule exE)
wenzelm@12944
   746
  apply (rule_tac x = rb in exI)
wenzelm@12944
   747
  apply (rule conjI)
wenzelm@12944
   748
   prefer 2
wenzelm@12944
   749
   apply (drule_tac x = ma in fun_cong)
wenzelm@12944
   750
   apply (simp add: eq_sym_conv)
wenzelm@12944
   751
  apply (simp (no_asm) add: o_def subst_comp_tel [symmetric])
wenzelm@12944
   752
  apply (rule subst_comp_tel [symmetric, THEN [2] trans])
wenzelm@12944
   753
  apply (simp add: o_def eq_sym_conv)
wenzelm@12944
   754
  apply (rule eq_free_eq_subst_tel)
wenzelm@12944
   755
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   756
  apply (subgoal_tac "ma \<noteq> na")
wenzelm@12944
   757
   prefer 2
wenzelm@12944
   758
   apply (frule new_tv_W, assumption)
wenzelm@12944
   759
   apply (erule conjE)
wenzelm@12944
   760
   apply (drule new_tv_subst_tel)
wenzelm@12944
   761
    apply (fast intro: new_tv_list_le dest: sym [THEN W_var_geD])
wenzelm@12944
   762
   apply (frule_tac n = m in new_tv_W, assumption)
wenzelm@12944
   763
   apply (erule conjE)
wenzelm@12944
   764
   apply (drule free_tv_app_subst_tel [THEN subsetD])
wenzelm@12944
   765
   apply (tactic {* fast_tac (set_cs addDs [sym RS thm "W_var_geD", thm "new_tv_list_le",
wenzelm@12944
   766
     thm "codD", thm "new_tv_not_free_tv"]) 1 *})
wenzelm@12944
   767
  apply (case_tac "na \<in> free_tv t - free_tv sa")
wenzelm@12944
   768
   prefer 2
wenzelm@12944
   769
   txt {* case @{text "na \<notin> free_tv t - free_tv sa"} *}
wenzelm@12944
   770
   apply simp
wenzelm@12944
   771
   defer
wenzelm@12944
   772
   txt {* case @{text "na \<in> free_tv t - free_tv sa"} *}
wenzelm@12944
   773
   apply simp
wenzelm@12944
   774
   apply (drule free_tv_app_subst_tel [THEN subsetD])
wenzelm@12944
   775
   apply (fastsimp dest: codD subst_comp_tel [THEN [2] trans]
wenzelm@12944
   776
     eq_subst_tel_eq_free simp add: free_tv_subst dom_def)
wenzelm@12944
   777
  apply fast
wenzelm@12944
   778
  done
wenzelm@12944
   779
wenzelm@12944
   780
lemma W_complete: "[] |- e :: t' ==>
wenzelm@12944
   781
    \<exists>s t. (\<exists>m. \<W> e [] n = Ok (s, t, m)) \<and> (\<exists>r. t' = $r t)"
wenzelm@12944
   782
  apply (cut_tac a = "[]" and s' = id_subst and e = e and t' = t' in W_complete_aux)
wenzelm@12944
   783
    apply simp_all
wenzelm@12944
   784
  done
wenzelm@12944
   785
wenzelm@12944
   786
wenzelm@12961
   787
section {* Equivalence of W and I *}
wenzelm@12944
   788
wenzelm@12944
   789
text {*
wenzelm@12944
   790
  Recursive definition of type inference algorithm @{text \<I>} for
wenzelm@12944
   791
  Mini-ML.
wenzelm@12944
   792
*}
wenzelm@12944
   793
wenzelm@12944
   794
consts
wenzelm@12944
   795
  I :: "expr \<Rightarrow> typ list \<Rightarrow> nat \<Rightarrow> subst \<Rightarrow> (subst \<times> typ \<times> nat) maybe"  ("\<I>")
wenzelm@12944
   796
primrec
wenzelm@12944
   797
  "\<I> (Var i) a n s = (if i < length a then Ok (s, a ! i, n) else Fail)"
wenzelm@12944
   798
  "\<I> (Abs e) a n s = ((s, t, m) := \<I> e (TVar n # a) (Suc n) s;
wenzelm@12944
   799
    Ok (s, TVar n -> t, m))"
wenzelm@12944
   800
  "\<I> (App e1 e2) a n s =
wenzelm@12944
   801
    ((s1, t1, m1) := \<I> e1 a n s;
wenzelm@12944
   802
    (s2, t2, m2) := \<I> e2 a m1 s1;
wenzelm@12944
   803
    u := mgu ($s2 t1) ($s2 t2 -> TVar m2);
wenzelm@12944
   804
    Ok($u o s2, TVar m2, Suc m2))"
wenzelm@12944
   805
wenzelm@12944
   806
text {* \medskip Correctness. *}
wenzelm@12944
   807
wenzelm@12944
   808
lemma I_correct_wrt_W: "!!a m s s' t n.
wenzelm@12944
   809
    new_tv m a \<and> new_tv m s \<Longrightarrow> \<I> e a m s = Ok (s', t, n) \<Longrightarrow>
wenzelm@12944
   810
    \<exists>r. \<W> e ($s a) m = Ok (r, $s' t, n) \<and> s' = ($r o s)"
wenzelm@12944
   811
  apply (atomize (full))
wenzelm@12944
   812
  apply (induct e)
wenzelm@12944
   813
    txt {* case @{text "Var n"} *}
wenzelm@12944
   814
    apply (simp add: app_subst_list split: split_if)
wenzelm@12944
   815
   txt {* case @{text "Abs e"} *}
wenzelm@12944
   816
   apply (tactic {* asm_full_simp_tac
wenzelm@12944
   817
     (simpset() setloop (split_inside_tac [thm "split_bind"])) 1 *})
wenzelm@12944
   818
   apply (intro strip)
wenzelm@12944
   819
   apply (rule conjI)
wenzelm@12944
   820
    apply (intro strip)
wenzelm@12944
   821
    apply (erule allE)+
wenzelm@12944
   822
    apply (erule impE)
wenzelm@12944
   823
     prefer 2 apply (fastsimp simp add: new_tv_subst)
wenzelm@12944
   824
    apply (tactic {* fast_tac (HOL_cs addIs [thm "new_tv_Suc_list" RS mp,
wenzelm@12944
   825
      thm "new_tv_subst_le", less_imp_le, lessI]) 1 *})
wenzelm@12944
   826
   apply (intro strip)
wenzelm@12944
   827
   apply (erule allE)+
wenzelm@12944
   828
   apply (erule impE)
wenzelm@12944
   829
    prefer 2 apply (fastsimp simp add: new_tv_subst)
wenzelm@12944
   830
   apply (tactic {* fast_tac (HOL_cs addIs [thm "new_tv_Suc_list" RS mp,
wenzelm@12944
   831
     thm "new_tv_subst_le", less_imp_le, lessI]) 1 *})
wenzelm@12944
   832
  txt {* case @{text "App e1 e2"} *}
wenzelm@12944
   833
  apply (tactic {* simp_tac (simpset () setloop (split_inside_tac [thm "split_bind"])) 1 *})
wenzelm@12944
   834
  apply (intro strip)
wenzelm@12944
   835
  apply (rename_tac s1' t1 n1 s2' t2 n2 sa)
wenzelm@12944
   836
  apply (rule conjI)
wenzelm@12944
   837
   apply fastsimp
wenzelm@12944
   838
  apply (intro strip)
wenzelm@12944
   839
  apply (rename_tac s1 t1' n1')
wenzelm@12944
   840
  apply (erule_tac x = a in allE)
wenzelm@12944
   841
  apply (erule_tac x = m in allE)
wenzelm@12944
   842
  apply (erule_tac x = s in allE)
wenzelm@12944
   843
  apply (erule_tac x = s1' in allE)
wenzelm@12944
   844
  apply (erule_tac x = t1 in allE)
wenzelm@12944
   845
  apply (erule_tac x = n1 in allE)
wenzelm@12944
   846
  apply (erule_tac x = a in allE)
wenzelm@12944
   847
  apply (erule_tac x = n1 in allE)
wenzelm@12944
   848
  apply (erule_tac x = s1' in allE)
wenzelm@12944
   849
  apply (erule_tac x = s2' in allE)
wenzelm@12944
   850
  apply (erule_tac x = t2 in allE)
wenzelm@12944
   851
  apply (erule_tac x = n2 in allE)
wenzelm@12944
   852
  apply (rule conjI)
wenzelm@12944
   853
   apply (intro strip)
wenzelm@12944
   854
   apply (rule notI)
wenzelm@12944
   855
   apply simp
wenzelm@12944
   856
   apply (erule impE)
wenzelm@12944
   857
    apply (frule new_tv_subst_tel, assumption)
wenzelm@12944
   858
    apply (drule_tac a = "$s a" in new_tv_W, assumption)
wenzelm@12944
   859
    apply (fastsimp dest: sym [THEN W_var_geD] new_tv_subst_le new_tv_list_le)
wenzelm@12944
   860
   apply (fastsimp simp add: subst_comp_tel)
wenzelm@12944
   861
  apply (intro strip)
wenzelm@12944
   862
  apply (rename_tac s2 t2' n2')
wenzelm@12944
   863
  apply (rule conjI)
wenzelm@12944
   864
   apply (intro strip)
wenzelm@12944
   865
   apply (rule notI)
wenzelm@12944
   866
   apply simp
wenzelm@12944
   867
   apply (erule impE)
wenzelm@12944
   868
   apply (frule new_tv_subst_tel, assumption)
wenzelm@12944
   869
   apply (drule_tac a = "$s a" in new_tv_W, assumption)
wenzelm@12944
   870
    apply (fastsimp dest: sym [THEN W_var_geD] new_tv_subst_le new_tv_list_le)
wenzelm@12944
   871
   apply (fastsimp simp add: subst_comp_tel subst_comp_te)
wenzelm@12944
   872
  apply (intro strip)
wenzelm@12944
   873
  apply (erule (1) notE impE)
wenzelm@12944
   874
  apply (erule (1) notE impE)
wenzelm@12944
   875
  apply (erule exE)
wenzelm@12944
   876
  apply (erule conjE)
wenzelm@12944
   877
  apply (erule impE)
wenzelm@12944
   878
   apply (frule new_tv_subst_tel, assumption)
wenzelm@12944
   879
   apply (drule_tac a = "$s a" in new_tv_W, assumption)
wenzelm@12944
   880
   apply (fastsimp dest: sym [THEN W_var_geD] new_tv_subst_le new_tv_list_le)
wenzelm@12944
   881
  apply (erule (1) notE impE)
wenzelm@12944
   882
  apply (erule exE conjE)+
berghofe@13601
   883
  apply (simp (asm_lr) add: subst_comp_tel subst_comp_te o_def, (erule conjE)+, hypsubst)+
wenzelm@12944
   884
  apply (subgoal_tac "new_tv n2 s \<and> new_tv n2 r \<and> new_tv n2 ra")
wenzelm@12944
   885
   apply (simp add: new_tv_subst)
wenzelm@12944
   886
  apply (frule new_tv_subst_tel, assumption)
wenzelm@12944
   887
  apply (drule_tac a = "$s a" in new_tv_W, assumption)
wenzelm@12944
   888
  apply (tactic "safe_tac HOL_cs")
wenzelm@12944
   889
    apply (bestsimp dest: sym [THEN W_var_geD] new_tv_subst_le new_tv_list_le)
wenzelm@12944
   890
   apply (fastsimp dest: sym [THEN W_var_geD] new_tv_subst_le new_tv_list_le)
wenzelm@12944
   891
  apply (drule_tac e = expr1 in sym [THEN W_var_geD])
wenzelm@12944
   892
  apply (drule new_tv_subst_tel, assumption)
wenzelm@12944
   893
  apply (drule_tac ts = "$s a" in new_tv_list_le, assumption)
wenzelm@12944
   894
  apply (drule new_tv_subst_tel, assumption)
wenzelm@12944
   895
  apply (bestsimp dest: new_tv_W simp add: subst_comp_tel)
wenzelm@12944
   896
  done
wenzelm@12944
   897
wenzelm@12944
   898
lemma I_complete_wrt_W: "!!a m s.
wenzelm@12944
   899
    new_tv m a \<and> new_tv m s \<Longrightarrow> \<I> e a m s = Fail \<Longrightarrow> \<W> e ($s a) m = Fail"
wenzelm@12944
   900
  apply (atomize (full))
wenzelm@12944
   901
  apply (induct e)
wenzelm@12944
   902
    apply (simp add: app_subst_list)
wenzelm@12944
   903
   apply (simp (no_asm))
wenzelm@12944
   904
   apply (intro strip)
wenzelm@12944
   905
   apply (subgoal_tac "TVar m # $s a = $s (TVar m # a)")
wenzelm@12944
   906
    apply (tactic {* asm_simp_tac (HOL_ss addsimps
wenzelm@12944
   907
      [thm "new_tv_Suc_list", lessI RS less_imp_le RS thm "new_tv_subst_le"]) 1 *})
wenzelm@12944
   908
    apply (erule conjE)
wenzelm@12944
   909
    apply (drule new_tv_not_free_tv [THEN not_free_impl_id])
wenzelm@12944
   910
    apply (simp (no_asm_simp))
wenzelm@12944
   911
  apply (simp (no_asm_simp))
wenzelm@12944
   912
  apply (intro strip)
wenzelm@12944
   913
  apply (erule exE)+
wenzelm@12944
   914
  apply (erule conjE)+
wenzelm@12944
   915
  apply (drule I_correct_wrt_W [COMP swap_prems_rl])
wenzelm@12944
   916
   apply fast
wenzelm@12944
   917
  apply (erule exE)
wenzelm@12944
   918
  apply (erule conjE)
wenzelm@12944
   919
  apply hypsubst
wenzelm@12944
   920
  apply (simp (no_asm_simp))
wenzelm@12944
   921
  apply (erule disjE)
wenzelm@12944
   922
   apply (rule disjI1)
wenzelm@12944
   923
   apply (simp (no_asm_use) add: o_def subst_comp_tel)
wenzelm@12944
   924
   apply (erule allE, erule allE, erule allE, erule impE, erule_tac [2] impE,
wenzelm@12944
   925
     erule_tac [2] asm_rl, erule_tac [2] asm_rl)
wenzelm@12944
   926
   apply (rule conjI)
wenzelm@12944
   927
    apply (fast intro: W_var_ge [THEN new_tv_list_le])
wenzelm@12944
   928
   apply (rule new_tv_subst_comp_2)
wenzelm@12944
   929
    apply (fast intro: W_var_ge [THEN new_tv_subst_le])
wenzelm@12944
   930
   apply (fast intro!: new_tv_subst_tel intro: new_tv_W [THEN conjunct1])
wenzelm@12944
   931
  apply (rule disjI2)
wenzelm@12944
   932
  apply (erule exE)+
wenzelm@12944
   933
  apply (erule conjE)
wenzelm@12944
   934
  apply (drule I_correct_wrt_W [COMP swap_prems_rl])
wenzelm@12944
   935
   apply (rule conjI)
wenzelm@12944
   936
   apply (fast intro: W_var_ge [THEN new_tv_list_le])
wenzelm@12944
   937
   apply (rule new_tv_subst_comp_1)
wenzelm@12944
   938
   apply (fast intro: W_var_ge [THEN new_tv_subst_le])
wenzelm@12944
   939
   apply (fast intro!: new_tv_subst_tel intro: new_tv_W [THEN conjunct1])
wenzelm@12944
   940
  apply (erule exE)
wenzelm@12944
   941
  apply (erule conjE)
wenzelm@12944
   942
  apply hypsubst
wenzelm@12944
   943
  apply (simp add: o_def subst_comp_te [symmetric] subst_comp_tel [symmetric])
wenzelm@12944
   944
  done
wenzelm@12944
   945
wenzelm@12944
   946
end