Type inference: Basic idea: ----------- - you know types of constants like true, 1, 0.1 etc. - you know the types of built-in operators like +, hd, tl, etc. - you know semantics of function application y = f x means type(f) = a -> b type(x) = a type(y) = b - in a conditional, type of predicate is boolean and types of both then and else expressions must be the same - etc. etc. Given text of function, use these kinds of rules to write down a set of type equations and solve them to find types. eg. x + 1 (type of x must int) reasoning: type of + in ML is either int x int -> int or real x real -> real type of 1 is int so type of x must be int eg. hd(x) type of hd is a list -> a (for all a) so x must be of (a list) eg. hd(x) + 1 from type of hd, we know type of x is (a list) from type of +, we know type of hd(x) is int so type of x is (int list) Equations: let type of x = t1 and return type of hd(x) be t2 Solve these equations: t1 -> t2 = (a list) -> a t2 = int These are equivalent to t1 = a list t2 = a t2 = int This means a = int and t1 = (int list) eg. S f g x = (f x) (g x) Assign type variables to parameters, return type and results of intermediate function applications (S f:t1 g:t2 x:t3):t6 = ((f x):t4 (g x):t5):t7 Write down equations: t1 = t3 -> t4 t2 = t3 -> t5 t4 = t5 -> t7 t6 = t7 Solve: t1 = t3 -> t5 -> t6 t2 = t3 -> t5 t4 = t5 -> t6 t7 = t6 Type of S combinator is (t3 -> t5 -> t6) -> (t3 -> t5) -> t3 -> t6 eg. S f g x = (f g) (f x) (S f:t1 g:t2 x:t3):t4 = ((f g):t5 (f x):t6):t7 t1 = t2 -> t5 t1 = t3 -> t6 t5 = t6 -> t7 t4 = t7 From first two equations, we get t2 -> t5 = t3 -> t6 So t2 = t3 and t5 = t6 Substituting in third equations, we get t6 = t6 -> t7 which is a circular definition. This means the function is not well-typed in our type system. eg. fun map(f,l) = if null(l) then nil else cons(f(hd(l)), map(f,tl(l))) fun map(f:a,l:b):c = if null(l) then nil else cons(f(hd(l)), map(f,tl(l))) b = b' list (from null(l)) c = d list (from nil being a return value) b = b'' list (from hd(l)) a = b'' -> r (from f(hd(l))) b = b''' list (from tl(l)) b = b''' (from map) c = d' list d' = r Solve to get type of map is (b' -> r) x (b' list) -> (r list) which makes sense. Lessons: ------------ - walk over definition of function and produce system of type equations (syntax-directed rules) - solve type equations: if you have more variables than constraints, the degrees of freedom correspond to universally quantified types (unification) - when solving type equations, you have to worry about circular definitions (occurs check in unification)