# Cs776 (Prasad)L4Poly1 Polymorphic Type System. cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression.

## Presentation on theme: "Cs776 (Prasad)L4Poly1 Polymorphic Type System. cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression."— Presentation transcript:

cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression of type-equality constraints fun fst (x,y) = x fst : ’a *’b -> ’a Support notion of instance of a type I 5 I : int -> int

cs776 (Prasad)L4Poly3 Polymorphic Type System Type constants int, bool, … Type variables ’a, …, ’’a, … Type constructors  ->, *, … Principal type of an expression is the most general type, which ML system infers. Type Checking Rule An expression of a type can legally appear in all contexts where an instance of that type can appear.

cs776 (Prasad)L4Poly4 Signature of Equality = : ’a * ’a -> bool ? Equality (“= ”) is not computable for all types. E.g., function values. So types (’a,’b, …) are partitioned into types that support equality (’’a, ’’b, …) types that do not support equality. = : ’’a * ’’a -> bool int, string, etc are equality types. They are closed under cartesian product, but not under function space constructor.

cs776 (Prasad)L4Poly5 Type Inference I (3,5)  (3,5) (int*int)->(int*int) (int*int) Principal type of I is the generalization of all possible types of its uses. Curry2 : (’a * ’b -> ’c) -> (’a -> ’b -> ’c) Uncurry2 : (’a -> ’b -> ’c) -> (’a * ’b -> ’c)

cs776 (Prasad)L4Poly6 Subtle Points The type of a use of a function must be an instance of the principal type inferred in the definition. The type of a value is fixed. So, multiple occurrences of a symbol denoting the same value (such as several uses of a formal parameter in a function body) must have identical type.

cs776 (Prasad)L4Poly7 Systematic Type Derivation fun c f g x = f(g(x)) Step1: Assign most general types to left- hand-side arguments and the (rhs) result. f : t1 g : t2 x : t3 f(g(x)) : t4 Thus, type of c is: c: t1 -> t2 -> t3 -> t4

cs776 (Prasad)L4Poly8 Step 2: Analyze and propagate type constraints –Application Rule If f x : t then x : t1 and f : t1 -> t, for some new t1. –Equality Rule If both x:t and x:t1 can be deduced for the value of a variable x, then t = t1. –Function Rule (t->u)=(t1->u1) iff (t=t1) /\ (u=u1)

cs776 (Prasad)L4Poly9 f(g x): t4 AR (g x) : t5 f : t5 -> t4 AR x : t6 g: t6 -> t5 ER t1 = t5 -> t4 t2 = t6 -> t5 t3 = t6 Step 3: Overall deduced type c : (t5 -> t4) -> (t6 -> t5) -> (t6 -> t4) (unary function composition)

cs776 (Prasad)L4Poly10 Example fun f x y = fst x + fst y given op + : int ->int -> int fst : ’a * ’b -> ’a Step 1 : x: t1 y : t2 (fst_1 x + fst_2 y) : t3 The two instantiations of fst need not have the same type. fst_1 : u1 * u2 -> u1 fst_2 : v1 * v2 -> v1 f: t1 -> t2 -> t3

cs776 (Prasad)L4Poly11 Step 2: Applying rule for + (fst_1 x) : int (fst_2 y) : int t3 = int Step 3: fst_1 : int*u2 -> int fst_2 : int*v2 -> int t1 = int * u2 t2 = int * v2 f: int * ’a -> int * ’b -> int

cs776 (Prasad)L4Poly12 Example (fixed point) fun fix f = f (fix f) 1. Assume f : ’a -> ’b 2. From (fix f = f (…)) infer fix : (’a -> ’b) -> ’b 3. From (... = f (fix f)) infer fix : (’a -> ’b) -> ’a fix : ’a -> ’a -> ’a

cs776 (Prasad)L4Poly13 Recursive Definition (curried function) fun f x y = f (f x) 0; f: (int -> ’a) -> int -> ’a fun f x y = f (f x) (f x y); f: (’a -> ’a) -> ’a -> ’a fun f f = f; (* identity function *) (* names of formals and functions come from disjoint namespaces *) fun f x y = f x; (* illegal *) fun f g = g f; (* illegal *)

cs776 (Prasad)L4Poly14 Example (ill-typed definition) fun selfApply f = f f 1. f_1:t1 (f_2 f_3):t2 selfApply : t1 -> t2 2. f_3 : t3 f_2 : t3 -> t2 3. t1 = t3 = t3 -> t2 (unsatisfiable) (cf. val selfApply = I I)

cs776 (Prasad)L4Poly15 Problematic Case fn x => (1, “a”); val it = fn : 'a -> int * string fn f => (f 1, f “a”); Type error “Least upper bound” of int and string does not exist, and the expression cannot be typed as (( ’a->’b) ->’b*’b) because the following expression is not type correct. ( (fn f => (f 1, f “a”)) (Real.Math.sqrt) );

cs776 (Prasad)L4Poly16 (cont’d) fn (x,y) => (size x, length y); val it = fn : string * 'a list -> int * int fn z => (size z, length z); Type Error string and list cannot be unified to obtain ’a -> (int * int). Or else, it will conflict with type instantiation rule, compromising type safety.

cs776 (Prasad)L4Poly17 Equivalence? (let val V = E in F end) =/= ((fn V => F) E) Even though both these expressions have the same behavior, the lambda abstraction is more restricted because it is type checked independently of the context of its use. In particular, the polymorphic type variable introduced in an abstraction must be treated differently from that introduced in a local definition.

Similar presentations