src/HOL/MiniML/W.thy
changeset 14422 b8da5f258b04
parent 5184 9b8547a9496a
child 14424 9a415e68cc06
--- a/src/HOL/MiniML/W.thy	Mon Mar 01 13:51:21 2004 +0100
+++ b/src/HOL/MiniML/W.thy	Tue Mar 02 01:32:23 2004 +0100
@@ -1,21 +1,18 @@
 (* Title:     HOL/MiniML/W.thy
    ID:        $Id$
-   Author:    Wolfgang Naraschewski and Tobias Nipkow
+   Author:    Dieter Nazareth, Wolfgang Naraschewski and Tobias Nipkow
    Copyright  1996 TU Muenchen
 
-Type inference algorithm W
+Correctness and completeness of type inference algorithm W
 *)
 
 
-W = MiniML + 
-
-types 
-        result_W = "(subst * typ * nat)option"
+theory W = MiniML:
 
-(* type inference algorithm W *)
+types result_W = "(subst * typ * nat)option"
 
-consts
-        W :: [expr, ctxt, nat] => result_W
+-- "type inference algorithm W"
+consts W :: "[expr, ctxt, nat] => result_W"
 
 primrec
   "W (Var i) A n =  
@@ -35,4 +32,554 @@
   "W (LET e1 e2) A n = ( (S1,t1,m1) := W e1 A n;
                          (S2,t2,m2) := W e2 ((gen ($S1 A) t1)#($S1 A)) m1;
                          Some( $S2 o S1, t2, m2) )"
+
+
+lemmas W_rules =
+ le_env_Cons 
+ le_type_scheme_refl 
+ le_env_refl 
+ bound_typ_instance_BVar 
+ not_FVar_le_Fun 
+ not_BVar_le_Fun 
+ le_env_Cons 
+ le_type_scheme_refl 
+ le_env_refl 
+ bound_typ_instance_BVar 
+ not_FVar_le_Fun 
+ not_BVar_le_Fun
+ has_type.intros
+ equalityE
+
+
+declare Suc_le_lessD [simp]
+declare less_imp_le [simp del]  (*the combination loops*)
+
+inductive_cases has_type_casesE:
+"A |- Var n :: t"
+"A |- Abs e :: t"
+"A |- App e1 e2 ::t"
+"A |- LET e1 e2 ::t"
+
+
+(* the resulting type variable is always greater or equal than the given one *)
+lemma W_var_ge [rule_format (no_asm)]: "!A n S t m. W e A n  = Some (S,t,m) --> n<=m"
+apply (induct_tac "e")
+(* case Var(n) *)
+apply (simp (no_asm) split add: split_option_bind)
+(* case Abs e *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (fast dest: Suc_leD)
+(* case App e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (blast intro: le_SucI le_trans)
+(* case LET e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (blast intro: le_trans)
+done
+
+declare W_var_ge [simp]
+
+lemma W_var_geD: "Some (S,t,m) = W e A n ==> n<=m"
+apply (simp add: eq_sym_conv)
+done
+
+lemma new_tv_compatible_W: "new_tv n A ==> Some (S,t,m) = W e A n ==> new_tv m A"
+apply (drule W_var_geD)
+apply (rule new_scheme_list_le)
+apply assumption
+apply assumption
+done
+
+lemma new_tv_bound_typ_inst_sch [rule_format (no_asm)]: "new_tv n sch --> new_tv (n + (min_new_bound_tv sch)) (bound_typ_inst (%b. TVar (b + n)) sch)"
+apply (induct_tac "sch")
+  apply simp
+ apply (simp add: add_commute)
+apply (intro strip)
+apply simp
+apply (erule conjE)
+apply (rule conjI)
+ apply (rule new_tv_le)
+  prefer 2 apply (assumption)
+ apply (rule add_le_mono)
+  apply (simp (no_asm))
+ apply (simp (no_asm) add: max_def)
+apply (rule new_tv_le)
+ prefer 2 apply (assumption)
+apply (rule add_le_mono)
+ apply (simp (no_asm))
+apply (simp (no_asm) add: max_def)
+done
+
+declare new_tv_bound_typ_inst_sch [simp]
+
+(* resulting type variable is new *)
+lemma new_tv_W [rule_format (no_asm)]: "!n A S t m. new_tv n A --> W e A n = Some (S,t,m) -->     
+                  new_tv m S & new_tv m t"
+apply (induct_tac "e")
+(* case Var n *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (intro strip)
+apply (drule new_tv_nth_nat_A)
+apply assumption
+apply (simp (no_asm_simp))
+(* case Abs e *)
+apply (simp (no_asm) add: new_tv_subst new_tv_Suc_list split add: split_option_bind)
+apply (intro strip)
+apply (erule_tac x = "Suc n" in allE)
+apply (erule_tac x = " (FVar n) #A" in allE)
+apply (fastsimp simp add: new_tv_subst new_tv_Suc_list)
+(* case App e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (intro strip)
+apply (rename_tac S1 t1 n1 S2 t2 n2 S3)
+apply (erule_tac x = "n" in allE)
+apply (erule_tac x = "A" in allE)
+apply (erule_tac x = "S1" in allE)
+apply (erule_tac x = "t1" in allE)
+apply (erule_tac x = "n1" in allE)
+apply (erule_tac x = "n1" in allE)
+apply (simp add: eq_sym_conv del: all_simps)
+apply (erule_tac x = "$S1 A" in allE)
+apply (erule_tac x = "S2" in allE)
+apply (erule_tac x = "t2" in allE)
+apply (erule_tac x = "n2" in allE)
+apply ( simp add: o_def rotate_Some)
+apply (rule conjI)
+apply (rule new_tv_subst_comp_2)
+apply (rule new_tv_subst_comp_2)
+apply (rule lessI [THEN less_imp_le, THEN new_tv_le])
+apply (rule_tac n = "n1" in new_tv_subst_le)
+apply (simp add: rotate_Some)
+apply (simp (no_asm_simp))
+apply (fast dest: W_var_geD intro: new_scheme_list_le new_tv_subst_scheme_list lessI [THEN less_imp_le [THEN new_tv_subst_le]])
+apply (erule sym [THEN mgu_new])
+apply (blast dest!: W_var_geD
+             intro: lessI [THEN less_imp_le, THEN new_tv_le] new_tv_subst_te 
+                    new_tv_subst_scheme_list new_scheme_list_le new_tv_le)
+
+apply (erule impE)
+apply (blast dest: W_var_geD intro: new_tv_subst_scheme_list new_scheme_list_le new_tv_le)
+apply clarsimp
+
+apply (rule lessI [THEN new_tv_subst_var])
+apply (erule sym [THEN mgu_new])
+apply (blast dest!: W_var_geD
+             intro: lessI [THEN less_imp_le, THEN new_tv_le] new_tv_subst_te 
+                    new_tv_subst_scheme_list new_scheme_list_le new_tv_le)
+
+apply (erule impE)
+apply (blast dest: W_var_geD intro: new_tv_subst_scheme_list new_scheme_list_le new_tv_le)
+apply clarsimp
+
+-- "41: case LET e1 e2"
+apply (simp (no_asm) split add: split_option_bind)
+apply (intro strip)
+apply (erule allE,erule allE,erule allE,erule allE,erule allE, erule impE, assumption, erule impE, assumption) 
+apply (erule conjE)
+apply (erule allE,erule allE,erule allE,erule allE,erule allE, erule impE, erule_tac [2] notE impE, tactic "assume_tac 2")
+apply (simp only: new_tv_def)
+apply (simp (no_asm_simp))
+apply (drule W_var_ge)+
+apply (rule allI)
+apply (intro strip)
+apply (simp only: free_tv_subst)
+apply (drule free_tv_app_subst_scheme_list [THEN subsetD])
+apply (best elim: less_le_trans)
+apply (erule conjE)
+apply (rule conjI)
+apply (simp only: o_def)
+apply (rule new_tv_subst_comp_2)
+apply (erule W_var_ge [THEN new_tv_subst_le])
+apply assumption
+apply assumption
+apply assumption
+done
+
+
+lemma free_tv_bound_typ_inst1 [rule_format (no_asm)]: "(v ~: free_tv sch) --> (v : free_tv (bound_typ_inst (TVar o S) sch)) --> (? x. v = S x)"
+apply (induct_tac "sch")
+apply simp
+apply simp
+apply (intro strip)
+apply (rule exI)
+apply (rule refl)
+apply simp
+done
+
+declare free_tv_bound_typ_inst1 [simp]
+
+lemma free_tv_W [rule_format (no_asm)]: "!n A S t m v. W e A n = Some (S,t,m) -->             
+          (v:free_tv S | v:free_tv t) --> v<n --> v:free_tv A"
+apply (induct_tac "e")
+(* case Var n *)
+apply (simp (no_asm) add: free_tv_subst split add: split_option_bind)
+apply (intro strip)
+apply (case_tac "v : free_tv (A!nat) ")
+ apply simp
+apply (drule free_tv_bound_typ_inst1)
+ apply (simp (no_asm) add: o_def)
+apply (erule exE)
+apply simp
+(* case Abs e *)
+apply (simp add: free_tv_subst split add: split_option_bind del: all_simps)
+apply (intro strip)
+apply (rename_tac S t n1 v)
+apply (erule_tac x = "Suc n" in allE)
+apply (erule_tac x = "FVar n # A" in allE)
+apply (erule_tac x = "S" in allE)
+apply (erule_tac x = "t" in allE)
+apply (erule_tac x = "n1" in allE)
+apply (erule_tac x = "v" in allE)
+apply (bestsimp del: W_rules intro: cod_app_subst simp add: less_Suc_eq)
+(* case App e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind del: all_simps)
+apply (intro strip)
+apply (rename_tac S t n1 S1 t1 n2 S2 v)
+apply (erule_tac x = "n" in allE)
+apply (erule_tac x = "A" in allE)
+apply (erule_tac x = "S" in allE)
+apply (erule_tac x = "t" in allE)
+apply (erule_tac x = "n1" in allE)
+apply (erule_tac x = "n1" in allE)
+apply (erule_tac x = "v" in allE)
+(* second case *)
+apply (erule_tac x = "$ S A" in allE)
+apply (erule_tac x = "S1" in allE)
+apply (erule_tac x = "t1" in allE)
+apply (erule_tac x = "n2" in allE)
+apply (erule_tac x = "v" in allE)
+apply (intro conjI impI | elim conjE)+
+ apply (simp add: rotate_Some o_def)
+ apply (drule W_var_geD)
+ apply (drule W_var_geD)
+ apply ( (frule less_le_trans) , (assumption))
+ apply clarsimp 
+ apply (drule free_tv_comp_subst [THEN subsetD])
+ apply (drule sym [THEN mgu_free])
+ apply clarsimp 
+ apply (fastsimp dest: free_tv_comp_subst [THEN subsetD] sym [THEN mgu_free] codD free_tv_app_subst_te [THEN subsetD] free_tv_app_subst_scheme_list [THEN subsetD] less_le_trans less_not_refl2 subsetD)
+apply simp
+apply (drule sym [THEN W_var_geD])
+apply (drule sym [THEN W_var_geD])
+apply ( (frule less_le_trans) , (assumption))
+apply clarsimp
+apply (drule mgu_free)
+apply (fastsimp dest: mgu_free codD free_tv_subst_var [THEN subsetD] free_tv_app_subst_te [THEN subsetD] free_tv_app_subst_scheme_list [THEN subsetD] less_le_trans subsetD)
+(* LET e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind del: all_simps)
+apply (intro strip)
+apply (rename_tac S1 t1 n2 S2 t2 n3 v)
+apply (erule_tac x = "n" in allE)
+apply (erule_tac x = "A" in allE)
+apply (erule_tac x = "S1" in allE)
+apply (erule_tac x = "t1" in allE)
+apply (rotate_tac -1)
+apply (erule_tac x = "n2" in allE)
+apply (rotate_tac -1)
+apply (erule_tac x = "v" in allE)
+apply (erule (1) notE impE)
+apply (erule allE,erule allE,erule allE,erule allE,erule allE,erule_tac  x = "v" in allE)
+apply (erule (1) notE impE)
+apply simp
+apply (rule conjI)
+apply (fast dest!: codD free_tv_app_subst_scheme_list [THEN subsetD] free_tv_o_subst [THEN subsetD] W_var_ge dest: less_le_trans)
+apply (fast dest!: codD free_tv_app_subst_scheme_list [THEN subsetD] W_var_ge dest: less_le_trans)
+done
+
+lemma weaken_A_Int_B_eq_empty: "(!x. x : A --> x ~: B) ==> A Int B = {}"
+apply fast
+done
+
+lemma weaken_not_elem_A_minus_B: "x ~: A | x : B ==> x ~: A - B"
+apply fast
+done
+
+(* correctness of W with respect to has_type *)
+lemma W_correct_lemma [rule_format (no_asm)]: "!A S t m n . new_tv n A --> Some (S,t,m) = W e A n --> $S A |- e :: t"
+apply (induct_tac "e")
+(* case Var n *)
+apply simp
+apply (intro strip)
+apply (rule has_type.VarI)
+apply (simp (no_asm))
+apply (simp (no_asm) add: is_bound_typ_instance)
+apply (rule exI)
+apply (rule refl)
+(* case Abs e *)
+apply (simp add: app_subst_list split add: split_option_bind)
+apply (intro strip)
+apply (erule_tac x = " (mk_scheme (TVar n)) # A" in allE)
+apply simp
+apply (rule has_type.AbsI)
+apply (drule le_refl [THEN le_SucI, THEN new_scheme_list_le])
+apply (drule sym)
+apply (erule allE)+
+apply (erule impE)
+apply (erule_tac [2] notE impE, tactic "assume_tac 2")
+apply (simp (no_asm_simp))
+apply assumption
+(* case App e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (intro strip)
+apply (rename_tac S1 t1 n1 S2 t2 n2 S3)
+apply (rule_tac ?t2.0 = "$ S3 t2" in has_type.AppI)
+apply (rule_tac S1 = "S3" in app_subst_TVar [THEN subst])
+apply (rule app_subst_Fun [THEN subst])
+apply (rule_tac t = "$S3 (t2 -> (TVar n2))" and s = "$S3 ($S2 t1) " in subst)
+apply simp
+apply (simp only: subst_comp_scheme_list [symmetric] o_def) 
+apply ((rule has_type_cl_sub [THEN spec]) , (rule has_type_cl_sub [THEN spec]))
+apply (simp add: eq_sym_conv)
+apply (simp add: subst_comp_scheme_list [symmetric] o_def has_type_cl_sub eq_sym_conv)
+apply (rule has_type_cl_sub [THEN spec])
+apply (frule new_tv_W)
+apply assumption
+apply (drule conjunct1)
+apply (frule new_tv_subst_scheme_list)
+apply (rule new_scheme_list_le)
+apply (rule W_var_ge)
+apply assumption
+apply assumption
+apply (erule thin_rl)
+apply (erule allE)+
+apply (drule sym)
+apply (drule sym)
+apply (erule thin_rl)
+apply (erule thin_rl)
+apply (erule (1) notE impE)
+apply (erule (1) notE impE)
+apply assumption
+(* case Let e1 e2 *)
+apply (simp (no_asm) split add: split_option_bind)
+apply (intro strip)
+(*by (rename_tac "w q m1 S1 t1 m2 S2 t n2" 1); *)
+apply (rename_tac S1 t1 m1 S2)
+apply (rule_tac ?t1.0 = "$ S2 t1" in has_type.LETI)
+ apply (simp (no_asm) add: o_def)
+ apply (simp only: subst_comp_scheme_list [symmetric])
+ apply (rule has_type_cl_sub [THEN spec])
+ apply (drule_tac x = "A" in spec)
+ apply (drule_tac x = "S1" in spec)
+ apply (drule_tac x = "t1" in spec)
+ apply (drule_tac x = "m1" in spec)
+ apply (drule_tac x = "n" in spec)
+ apply (erule (1) notE impE)
+ apply (simp add: eq_sym_conv)
+apply (simp (no_asm) add: o_def)
+apply (simp only: subst_comp_scheme_list [symmetric])
+apply (rule gen_subst_commutes [symmetric, THEN subst])
+ apply (rule_tac [2] app_subst_Cons [THEN subst])
+ apply (erule_tac [2] thin_rl)
+ apply (drule_tac [2] x = "gen ($S1 A) t1 # $ S1 A" in spec)
+ apply (drule_tac [2] x = "S2" in spec)
+ apply (drule_tac [2] x = "t" in spec)
+ apply (drule_tac [2] x = "m" in spec)
+ apply (drule_tac [2] x = "m1" in spec)
+ apply (frule_tac [2] new_tv_W)
+  prefer 2 apply (assumption)
+ apply (drule_tac [2] conjunct1)
+ apply (frule_tac [2] new_tv_subst_scheme_list)
+  apply (rule_tac [2] new_scheme_list_le)
+   apply (rule_tac [2] W_var_ge)
+   prefer 2 apply (assumption)
+  prefer 2 apply (assumption)
+ apply (erule_tac [2] impE)
+  apply (rule_tac [2] A = "$ S1 A" in new_tv_only_depends_on_free_tv_scheme_list)
+   prefer 2 apply simp
+   apply (fast)
+  prefer 2 apply (assumption)
+ prefer 2 apply simp
+apply (rule weaken_A_Int_B_eq_empty)
+apply (rule allI)
+apply (intro strip)
+apply (rule weaken_not_elem_A_minus_B)
+apply (case_tac "x < m1")
+ apply (rule disjI2)
+ apply (rule free_tv_gen_cons [THEN subst])
+ apply (rule free_tv_W)
+   apply assumption
+  apply simp
+ apply assumption
+apply (rule disjI1)
+apply (drule new_tv_W)
+apply assumption
+apply (drule conjunct2)
+apply (rule new_tv_not_free_tv)
+apply (rule new_tv_le)
+ prefer 2 apply (assumption)
+apply (simp add: not_less_iff_le)
+done
+
+(* Completeness of W w.r.t. has_type *)
+lemma W_complete_lemma [rule_format (no_asm)]: 
+  "ALL S' A t' n. $S' A |- e :: t' --> new_tv n A -->      
+               (EX S t. (EX m. W e A n = Some (S,t,m)) &   
+                       (EX R. $S' A = $R ($S A) & t' = $R t))"
+apply (induct_tac "e")
+   (* case Var n *)
+   apply (intro strip)
+   apply (simp (no_asm) cong add: conj_cong)
+   apply (erule has_type_casesE)
+   apply (simp add: is_bound_typ_instance)
+   apply (erule exE)
+   apply (hypsubst)
+   apply (rename_tac "S")
+   apply (rule_tac x = "%x. (if x < n then S' x else S (x - n))" in exI)
+   apply (rule conjI)
+   apply (simp (no_asm_simp))
+   apply (simp (no_asm_simp) add: bound_typ_inst_composed_subst [symmetric] new_tv_nth_nat_A o_def nth_subst 
+                             del: bound_typ_inst_composed_subst)
+
+  (* case Abs e *)
+  apply (intro strip)
+  apply (erule has_type_casesE)
+  apply (erule_tac x = "%x. if x=n then t1 else (S' x) " in allE)
+  apply (erule_tac x = " (FVar n) #A" in allE)
+  apply (erule_tac x = "t2" in allE)
+  apply (erule_tac x = "Suc n" in allE)
+  apply (bestsimp dest!: mk_scheme_injective cong: conj_cong split: split_option_bind)
+
+ (* case App e1 e2 *)
+ apply (intro strip)
+ apply (erule has_type_casesE)
+ apply (erule_tac x = "S'" in allE)
+ apply (erule_tac x = "A" in allE)
+ apply (erule_tac x = "t2 -> t'" in allE)
+ apply (erule_tac x = "n" in allE)
+ apply safe
+ apply (erule_tac x = "R" in allE)
+ apply (erule_tac x = "$ S A" in allE)
+ apply (erule_tac x = "t2" in allE)
+ apply (erule_tac x = "m" in allE)
+ apply simp
+ apply safe
+  apply (blast intro: sym [THEN W_var_geD] new_tv_W [THEN conjunct1] new_scheme_list_le new_tv_subst_scheme_list)
+ 
+ (** LEVEL 33 **)
+apply (subgoal_tac "$ (%x. if x=ma then t' else (if x: (free_tv t - free_tv Sa) then R x else Ra x)) ($ Sa t) = $ (%x. if x=ma then t' else (if x: (free_tv t - free_tv Sa) then R x else Ra x)) (ta -> (TVar ma))")
+apply (rule_tac [2] t = "$ (%x. if x = ma then t' else (if x: (free_tv t - free_tv Sa) then R x else Ra x)) ($ Sa t) " and s = " ($ Ra ta) -> t'" in ssubst)
+prefer 2 apply (simp (no_asm_simp) add: subst_comp_te) prefer 2
+apply (rule_tac [2] eq_free_eq_subst_te)
+prefer 2 apply (intro strip) prefer 2
+apply (subgoal_tac [2] "na ~=ma")
+ prefer 3 apply (best dest: new_tv_W sym [THEN W_var_geD] new_tv_not_free_tv new_tv_le)
+apply (case_tac [2] "na:free_tv Sa")
+(* n1 ~: free_tv S1 *)
+apply (frule_tac [3] not_free_impl_id)
+ prefer 3 apply (simp)
+(* na : free_tv Sa *)
+apply (drule_tac [2] A1 = "$ S A" in trans [OF _ subst_comp_scheme_list])
+apply (drule_tac [2] eq_subst_scheme_list_eq_free)
+ prefer 2 apply (fast intro: free_tv_W free_tv_le_new_tv dest: new_tv_W)
+prefer 2 apply (simp (no_asm_simp)) prefer 2
+apply (case_tac [2] "na:dom Sa")
+(* na ~: dom Sa *)
+ prefer 3 apply (simp add: dom_def)
+(* na : dom Sa *)
+apply (rule_tac [2] eq_free_eq_subst_te)
+prefer 2 apply (intro strip) prefer 2
+apply (subgoal_tac [2] "nb ~= ma")
+apply (frule_tac [3] new_tv_W) prefer 3 apply assumption
+apply (erule_tac [3] conjE)
+apply (drule_tac [3] new_tv_subst_scheme_list)
+   prefer 3 apply (fast intro: new_scheme_list_le dest: sym [THEN W_var_geD])
+  prefer 3 apply (fastsimp dest: new_tv_W new_tv_not_free_tv simp add: cod_def free_tv_subst)
+ prefer 2 apply (fastsimp simp add: cod_def free_tv_subst)
+prefer 2 apply (simp (no_asm)) prefer 2
+apply (rule_tac [2] eq_free_eq_subst_te)
+prefer 2 apply (intro strip) prefer 2
+apply (subgoal_tac [2] "na ~= ma")
+apply (frule_tac [3] new_tv_W) prefer 3 apply assumption
+apply (erule_tac [3] conjE)
+apply (drule_tac [3] sym [THEN W_var_geD])
+ prefer 3 apply (fast dest: new_scheme_list_le new_tv_subst_scheme_list new_tv_W new_tv_not_free_tv)
+apply (case_tac [2] "na: free_tv t - free_tv Sa")
+(* case na ~: free_tv t - free_tv Sa *)
+ prefer 3 
+ apply simp
+ apply fast
+(* case na : free_tv t - free_tv Sa *)
+prefer 2 apply simp prefer 2
+apply (drule_tac [2] A1 = "$ S A" and r = "$ R ($ S A)" in trans [OF _ subst_comp_scheme_list])
+apply (drule_tac [2] eq_subst_scheme_list_eq_free)
+ prefer 2 
+ apply (fast intro: free_tv_W free_tv_le_new_tv dest: new_tv_W)
+(** LEVEL 73 **)
+ prefer 2 apply (simp add: free_tv_subst dom_def)
+apply (simp (no_asm_simp) split add: split_option_bind)
+apply safe
+apply (drule mgu_Some)
+ apply fastsimp  
+(** LEVEL 78 *)
+apply (drule mgu_mg, assumption)
+apply (erule exE)
+apply (rule_tac x = "Rb" in exI)
+apply (rule conjI)
+apply (drule_tac [2] x = "ma" in fun_cong)
+ prefer 2 apply (simp add: eq_sym_conv)
+apply (simp (no_asm) add: subst_comp_scheme_list)
+apply (simp (no_asm) add: subst_comp_scheme_list [symmetric])
+apply (rule_tac A2 = "($ Sa ($ S A))" in trans [OF _ subst_comp_scheme_list [symmetric]])
+apply (simp add: o_def eq_sym_conv)
+apply (drule_tac s = "Some ?X" in sym)
+apply (rule eq_free_eq_subst_scheme_list)
+apply safe
+apply (subgoal_tac "ma ~= na")
+apply (frule_tac [2] new_tv_W) prefer 2 apply assumption
+apply (erule_tac [2] conjE)
+apply (drule_tac [2] new_tv_subst_scheme_list)
+ prefer 2 apply (fast intro: new_scheme_list_le dest: sym [THEN W_var_geD])
+apply (frule_tac [2] n = "m" in new_tv_W) prefer 2 apply assumption
+apply (erule_tac [2] conjE)
+apply (drule_tac [2] free_tv_app_subst_scheme_list [THEN subsetD])
+ apply (tactic {* 
+   (fast_tac (set_cs addDs [sym RS thm "W_var_geD", thm "new_scheme_list_le", thm "codD",
+   thm "new_tv_not_free_tv"]) 2) *})
+apply (case_tac "na: free_tv t - free_tv Sa")
+(* case na ~: free_tv t - free_tv Sa *)
+ prefer 2 apply simp apply blast
+(* case na : free_tv t - free_tv Sa *)
+apply simp
+apply (drule free_tv_app_subst_scheme_list [THEN subsetD])
+ apply (fastsimp dest: codD trans [OF _ subst_comp_scheme_list]
+                       eq_subst_scheme_list_eq_free 
+             simp add: free_tv_subst dom_def)
+(* case Let e1 e2 *)
+apply (erule has_type_casesE)
+apply (erule_tac x = "S'" in allE)
+apply (erule_tac x = "A" in allE)
+apply (erule_tac x = "t1" in allE)
+apply (erule_tac x = "n" in allE)
+apply (erule (1) notE impE)
+apply (erule (1) notE impE)
+apply safe  
+apply (simp (no_asm_simp))
+apply (erule_tac x = "R" in allE)
+apply (erule_tac x = "gen ($ S A) t # $ S A" in allE)
+apply (erule_tac x = "t'" in allE)
+apply (erule_tac x = "m" in allE)
+apply simp
+apply (drule mp)
+apply (rule has_type_le_env)
+apply assumption
+apply (simp (no_asm))
+apply (rule gen_bound_typ_instance)
+apply (drule mp)
+apply (frule new_tv_compatible_W)
+apply (rule sym)
+apply assumption
+apply (fast dest: new_tv_compatible_gen new_tv_subst_scheme_list new_tv_W)
+apply safe
+apply simp
+apply (rule_tac x = "Ra" in exI)
+apply (simp (no_asm) add: o_def subst_comp_scheme_list [symmetric])
+done
+
+
+lemma W_complete: "[] |- e :: t' ==>  (? S t. (? m. W e [] n = Some(S,t,m)) &   
+                                  (? R. t' = $ R t))"
+apply (cut_tac A = "[]" and S' = "id_subst" and e = "e" and t' = "t'" in W_complete_lemma)
+apply simp_all
+done
+
 end