Type Inference II David Walker CS 510 ML-style Polymorphism 2 characteristics: prenex (let) polymorphism let f : all [a,b,c].t = ... in e polymorphic quantifiers appear in outermost positions polymorphic values can’t be arguments/results of functions, can’t be stored reason: completeness of type inference value restriction let x = v in e reason: soundness of type inference Value restriction Polymorphic generalization may occur over values only let x : (all [a]. (a -> a) ref) = ref (fn x => x) in x := (fn x => x + 1); (!x) true (* error *) not a value Generalization over non-values causes unsoundness Functions, lists, pairs,data cons. are values references, expressions that raise exns, perform I/O, function applications are not 1st-Class Polymorphism Question: where to generalize values with (monomorphic) schematic types to polymorphic types eg: fn(x).fn(y).y has type all [a].all [b]. a -> b -> b all [a]. a -> (all [b] . b -> b) which one do we pick? the first can be an argument to • (int -> bool -> bool) -> bool the second returns polymorphic functions z that can be applied to values with different types • z true; z 3 Prenex Polymorphism Solution: restrict to prenex quantification (type inference for the general case undecideable) generalize at let-bound values: G |- v : t, q (I,q) -> (S,{}) a1,...,an = FV(S(t)) - FV(G) G,x:all[a1,...,an].S(t) |- e : t’,q’ ------------------------------------------------------------G |- let x = v in e : t’,q’ a polymorphic value is always instantiated: G(f) = all[a1,...,an].t (a1,...,an are fresh) ----------------------------------------------------G |- f : t,{} Advanced Type Inf ML pushes the limit of complete type inf. 1st-class universal and existential poly, subtyping, bounded quantification make complete type inference impossible Nex step: Require some type annotations goal: require annotations where useful as documentation goal: omit type annotations where they are “obvious” and common Most languages (Java, C++, C) require some type annotations anyway Some Stats [PT 98] Type instantiation occurs all the time every third line of code Anonymous function declarations occurs fairly often 1/10 lines to 1/100 lines depending on style Local variable declarations 1/12 lines Local functions bound to variables 1/66 lines Consequences Type instantiation is the first priority every third line of ML-style code Anonymous function declarations are the next priority 1/10 lines to 1/100 lines depending on style Local variable declarations would be nice 1/12 lines 1/66 lines (functions) Bi-directional Type Inf Two interacting judgements type checking G |- e <= t we can check that e has the type t type t is an input to the judgement type synthesis G |- e => t we can synthesize the most general type t from the expression e and context G type t is an output of the judgement Note: we have been doing type synthesis all along More on Bi-Directional TI ..... on your next homework! End!