3 Author: Markus Wenzel, TU Muenchen |
3 Author: Markus Wenzel, TU Muenchen |
4 |
4 |
5 Correctness of Milner's type inference algorithm W (let-free version). |
5 Correctness of Milner's type inference algorithm W (let-free version). |
6 *) |
6 *) |
7 |
7 |
8 header {* Milner's type inference algorithm~W (let-free version) *}; |
8 header {* Milner's type inference algorithm~W (let-free version) *} |
9 |
9 |
10 theory W_correct = Main + Type:; |
10 theory W_correct = Main + Type: |
11 |
11 |
12 text_raw {* |
12 text_raw {* |
13 \footnote{Based upon \url{http://isabelle.in.tum.de/library/HOL/W0} |
13 \footnote{Based upon \url{http://isabelle.in.tum.de/library/HOL/W0} |
14 by Dieter Nazareth and Tobias Nipkow.} |
14 by Dieter Nazareth and Tobias Nipkow.} |
15 *}; |
15 *} |
16 |
16 |
17 |
17 |
18 subsection "Mini ML with type inference rules"; |
18 subsection "Mini ML with type inference rules" |
19 |
19 |
20 datatype |
20 datatype |
21 expr = Var nat | Abs expr | App expr expr; |
21 expr = Var nat | Abs expr | App expr expr |
22 |
22 |
23 |
23 |
24 text {* Type inference rules. *}; |
24 text {* Type inference rules. *} |
25 |
25 |
26 consts |
26 consts |
27 has_type :: "(typ list * expr * typ) set"; |
27 has_type :: "(typ list * expr * typ) set" |
28 |
28 |
29 syntax |
29 syntax |
30 "_has_type" :: "[typ list, expr, typ] => bool" |
30 "_has_type" :: "[typ list, expr, typ] => bool" |
31 ("((_) |-/ (_) :: (_))" [60, 0, 60] 60); |
31 ("((_) |-/ (_) :: (_))" [60, 0, 60] 60) |
32 translations |
32 translations |
33 "a |- e :: t" == "(a,e,t) : has_type"; |
33 "a |- e :: t" == "(a,e,t) : has_type" |
34 |
34 |
35 inductive has_type |
35 inductive has_type |
36 intros [simp] |
36 intros [simp] |
37 Var: "n < length a ==> a |- Var n :: a ! n" |
37 Var: "n < length a ==> a |- Var n :: a ! n" |
38 Abs: "t1#a |- e :: t2 ==> a |- Abs e :: t1 -> t2" |
38 Abs: "t1#a |- e :: t2 ==> a |- Abs e :: t1 -> t2" |
39 App: "a |- e1 :: t2 -> t1 ==> a |- e2 :: t2 |
39 App: "a |- e1 :: t2 -> t1 ==> a |- e2 :: t2 |
40 ==> a |- App e1 e2 :: t1"; |
40 ==> a |- App e1 e2 :: t1" |
41 |
41 |
42 |
42 |
43 text {* Type assigment is closed wrt.\ substitution. *}; |
43 text {* Type assigment is closed wrt.\ substitution. *} |
44 |
44 |
45 lemma has_type_subst_closed: "a |- e :: t ==> $s a |- e :: $s t"; |
45 lemma has_type_subst_closed: "a |- e :: t ==> $s a |- e :: $s t" |
46 proof -; |
46 proof - |
47 assume "a |- e :: t"; |
47 assume "a |- e :: t" |
48 thus ?thesis (is "?P a e t"); |
48 thus ?thesis (is "?P a e t") |
49 proof (induct (open) ?P a e t); |
49 proof (induct (open) ?P a e t) |
50 case Var; |
50 case Var |
51 hence "n < length (map ($ s) a)"; by simp; |
51 hence "n < length (map ($ s) a)" by simp |
52 hence "map ($ s) a |- Var n :: map ($ s) a ! n"; |
52 hence "map ($ s) a |- Var n :: map ($ s) a ! n" |
53 by (rule has_type.Var); |
53 by (rule has_type.Var) |
54 also; have "map ($ s) a ! n = $ s (a ! n)"; |
54 also have "map ($ s) a ! n = $ s (a ! n)" |
55 by (rule nth_map); |
55 by (rule nth_map) |
56 also; have "map ($ s) a = $ s a"; |
56 also have "map ($ s) a = $ s a" |
57 by (simp only: app_subst_list); |
57 by (simp only: app_subst_list) |
58 finally; show "?P a (Var n) (a ! n)"; .; |
58 finally show "?P a (Var n) (a ! n)" . |
59 next; |
59 next |
60 case Abs; |
60 case Abs |
61 hence "$ s t1 # map ($ s) a |- e :: $ s t2"; |
61 hence "$ s t1 # map ($ s) a |- e :: $ s t2" |
62 by (simp add: app_subst_list); |
62 by (simp add: app_subst_list) |
63 hence "map ($ s) a |- Abs e :: $ s t1 -> $ s t2"; |
63 hence "map ($ s) a |- Abs e :: $ s t1 -> $ s t2" |
64 by (rule has_type.Abs); |
64 by (rule has_type.Abs) |
65 thus "?P a (Abs e) (t1 -> t2)"; |
65 thus "?P a (Abs e) (t1 -> t2)" |
66 by (simp add: app_subst_list); |
66 by (simp add: app_subst_list) |
67 next; |
67 next |
68 case App; |
68 case App |
69 thus "?P a (App e1 e2) t1"; by simp; |
69 thus "?P a (App e1 e2) t1" by simp |
70 qed; |
70 qed |
71 qed; |
71 qed |
72 |
72 |
73 |
73 |
74 subsection {* Type inference algorithm W *}; |
74 subsection {* Type inference algorithm W *} |
75 |
75 |
76 consts |
76 consts |
77 W :: "[expr, typ list, nat] => (subst * typ * nat) maybe"; |
77 W :: "[expr, typ list, nat] => (subst * typ * nat) maybe" |
78 |
78 |
79 primrec |
79 primrec |
80 "W (Var i) a n = |
80 "W (Var i) a n = |
81 (if i < length a then Ok (id_subst, a ! i, n) else Fail)" |
81 (if i < length a then Ok (id_subst, a ! i, n) else Fail)" |
82 "W (Abs e) a n = |
82 "W (Abs e) a n = |
84 Ok (s, (s n) -> t, m))" |
84 Ok (s, (s n) -> t, m))" |
85 "W (App e1 e2) a n = |
85 "W (App e1 e2) a n = |
86 ((s1, t1, m1) := W e1 a n; |
86 ((s1, t1, m1) := W e1 a n; |
87 (s2, t2, m2) := W e2 ($s1 a) m1; |
87 (s2, t2, m2) := W e2 ($s1 a) m1; |
88 u := mgu ($ s2 t1) (t2 -> TVar m2); |
88 u := mgu ($ s2 t1) (t2 -> TVar m2); |
89 Ok ($u o $s2 o s1, $u (TVar m2), Suc m2))"; |
89 Ok ($u o $s2 o s1, $u (TVar m2), Suc m2))" |
90 |
90 |
91 |
91 |
92 subsection {* Correctness theorem *}; |
92 subsection {* Correctness theorem *} |
93 |
93 |
94 theorem W_correct: "W e a n = Ok (s, t, m) ==> $ s a |- e :: t"; |
94 theorem W_correct: "W e a n = Ok (s, t, m) ==> $ s a |- e :: t" |
95 proof -; |
95 proof - |
96 assume W_ok: "W e a n = Ok (s, t, m)"; |
96 assume W_ok: "W e a n = Ok (s, t, m)" |
97 have "ALL a s t m n. Ok (s, t, m) = W e a n --> $ s a |- e :: t" |
97 have "ALL a s t m n. Ok (s, t, m) = W e a n --> $ s a |- e :: t" |
98 (is "?P e"); |
98 (is "?P e") |
99 proof (induct (stripped) e); |
99 proof (induct (stripped) e) |
100 fix a s t m n; |
100 fix a s t m n |
101 { |
101 { |
102 fix i; |
102 fix i |
103 assume "Ok (s, t, m) = W (Var i) a n"; |
103 assume "Ok (s, t, m) = W (Var i) a n" |
104 thus "$ s a |- Var i :: t"; by (simp split: if_splits); |
104 thus "$ s a |- Var i :: t" by (simp split: if_splits) |
105 next; |
105 next |
106 fix e; assume hyp: "?P e"; |
106 fix e assume hyp: "?P e" |
107 assume "Ok (s, t, m) = W (Abs e) a n"; |
107 assume "Ok (s, t, m) = W (Abs e) a n" |
108 then; obtain t' where "t = s n -> t'" |
108 then obtain t' where "t = s n -> t'" |
109 and "Ok (s, t', m) = W e (TVar n # a) (Suc n)"; |
109 and "Ok (s, t', m) = W e (TVar n # a) (Suc n)" |
110 by (auto split: bind_splits); |
110 by (auto split: bind_splits) |
111 with hyp; show "$ s a |- Abs e :: t"; |
111 with hyp show "$ s a |- Abs e :: t" |
112 by (force intro: has_type.Abs); |
112 by (force intro: has_type.Abs) |
113 next; |
113 next |
114 fix e1 e2; assume hyp1: "?P e1" and hyp2: "?P e2"; |
114 fix e1 e2 assume hyp1: "?P e1" and hyp2: "?P e2" |
115 assume "Ok (s, t, m) = W (App e1 e2) a n"; |
115 assume "Ok (s, t, m) = W (App e1 e2) a n" |
116 then; obtain s1 t1 n1 s2 t2 n2 u where |
116 then obtain s1 t1 n1 s2 t2 n2 u where |
117 s: "s = $ u o $ s2 o s1" |
117 s: "s = $ u o $ s2 o s1" |
118 and t: "t = u n2" |
118 and t: "t = u n2" |
119 and mgu_ok: "mgu ($ s2 t1) (t2 -> TVar n2) = Ok u" |
119 and mgu_ok: "mgu ($ s2 t1) (t2 -> TVar n2) = Ok u" |
120 and W1_ok: "W e1 a n = Ok (s1, t1, n1)" |
120 and W1_ok: "W e1 a n = Ok (s1, t1, n1)" |
121 and W2_ok: "W e2 ($ s1 a) n1 = Ok (s2, t2, n2)"; |
121 and W2_ok: "W e2 ($ s1 a) n1 = Ok (s2, t2, n2)" |
122 by (auto split: bind_splits); |
122 by (auto split: bind_splits) |
123 show "$ s a |- App e1 e2 :: t"; |
123 show "$ s a |- App e1 e2 :: t" |
124 proof (rule has_type.App); |
124 proof (rule has_type.App) |
125 from s; have s': "$ u ($ s2 ($ s1 a)) = $s a"; |
125 from s have s': "$ u ($ s2 ($ s1 a)) = $s a" |
126 by (simp add: subst_comp_tel o_def); |
126 by (simp add: subst_comp_tel o_def) |
127 show "$s a |- e1 :: $ u t2 -> t"; |
127 show "$s a |- e1 :: $ u t2 -> t" |
128 proof -; |
128 proof - |
129 from hyp1 W1_ok [symmetric]; have "$ s1 a |- e1 :: t1"; |
129 from hyp1 W1_ok [symmetric] have "$ s1 a |- e1 :: t1" |
130 by blast; |
130 by blast |
131 hence "$ u ($ s2 ($ s1 a)) |- e1 :: $ u ($ s2 t1)"; |
131 hence "$ u ($ s2 ($ s1 a)) |- e1 :: $ u ($ s2 t1)" |
132 by (intro has_type_subst_closed); |
132 by (intro has_type_subst_closed) |
133 with s' t mgu_ok; show ?thesis; by simp; |
133 with s' t mgu_ok show ?thesis by simp |
134 qed; |
134 qed |
135 show "$ s a |- e2 :: $ u t2"; |
135 show "$ s a |- e2 :: $ u t2" |
136 proof -; |
136 proof - |
137 from hyp2 W2_ok [symmetric]; |
137 from hyp2 W2_ok [symmetric] |
138 have "$ s2 ($ s1 a) |- e2 :: t2"; by blast; |
138 have "$ s2 ($ s1 a) |- e2 :: t2" by blast |
139 hence "$ u ($ s2 ($ s1 a)) |- e2 :: $ u t2"; |
139 hence "$ u ($ s2 ($ s1 a)) |- e2 :: $ u t2" |
140 by (rule has_type_subst_closed); |
140 by (rule has_type_subst_closed) |
141 with s'; show ?thesis; by simp; |
141 with s' show ?thesis by simp |
142 qed; |
142 qed |
143 qed; |
143 qed |
144 }; |
144 } |
145 qed; |
145 qed |
146 with W_ok [symmetric]; show ?thesis; by blast; |
146 with W_ok [symmetric] show ?thesis by blast |
147 qed; |
147 qed |
148 |
148 |
149 end; |
149 end |