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