* Review of types and type checking ** What is a "type"? *** Specifications: abstract data type *** Models (of specifications) *** type checking: name (or expression) *** link between these views is focus of our study ** What is a type error? *** Seals (Morris, 1973) **** seal mechanism **** invariant preservation ** Representation independence * The core language type system for SML ** Type checking ** Reconstructing (Infering) type declarations for monomorphic expressions ** Polymorphism *** explicit ------------------ val id = fn (t:type) => (fn (a:t) => a) id(int)(3) id(bool)(true) ------------------ *** implicit ------------------ val id = (fn (a:'t) => a) id(3) id(true) ------------------ ------------------ val id = (fn a => a) ------------------ ** Reconstruction of polymorphic types *** Basic algorithm *** Let expressions and Generic type variables **** heterogeneous application of function argument --------------- (fn f => pair(f(3)) (f(true))) --------------- **** heterogeneous application of declared functions ------------------- let val f = (fn a => a) in pair(f(3)) (f(true)) end; ------------------- --------------- (fn g => let val f = g in pair(f(3)) (f(true)) end; --------------- *** Extended algorithm ** Inference system ** Limitations *** No recursive types: --------------- - datatype 'a stream = STR of unit -> ('a * 'a stream); - exception empty; - val emtpy_str = STR (fn x => raise empty); val emtpy_str = STR fn : 'a stream - fun ones () = (1, STR ones); val ones = fn : unit -> int * int stream - ones(); val it = (1,STR fn) : int * int stream --------------- *** Polymorphic functions are not first-class objects! ------------------ - fun F f = fn (a,b) => (f(a), f(b)); val F = fn : ('a -> 'b) -> 'a * 'a -> 'b * 'b ------------------ * Type reconstruction algorithm overview ** Data Structures *** environment (map from ids to types) *** type expressions (type variables, type constructors) *** stack of type variables (allows generic/non-generic distinction) *** substitutions ** Operations *** environment (expand, get value, ...) *** type variables *** type constructors *** type expressions *** stack of type variables (push, pop) *** substitutions ** Unification *** Specification **** Definitions ***** Terms, Term algebra ***** Substitutions ***** Unifiers, most general unifiers **** the problem **** basic algorithm ------------------ fun unify(VAR x,VAR y) = if Variable.equal(VAR x, VAR y) then Substitution.null else Substitution.singleton(VAR x, VAR y) | unify(x as TERM(f,args), VAR y) = unify(VAR y, x) | unify(VAR x, y as TERM(f,args)) = if Term.occurs(VAR x, y) then raise Failure else Substitution.singleton(VAR x, y) | unify(x as TERM(f,fargs), y as TERM(g,gargs)) = if not (Constructor.equal(f,g) orelse length(fargs) = length(gargs)) then raise Failure else let fun unifyargs(t1::rest1, t2::rest2, sigma) = let val tau = unify(t1,t2) in let val sigma' = Substitution.compose(tau, sigma) in if rest1 = [] then sigma' else unifyargs(rest1,rest2,sigma') end end in unifyargs(fargs,gargs,Substitution.null) end; ------------------ ** complexity ---------------- -fun pair x y = (fn z => z x y); val pair = fn : 'a -> 'b -> ('a -> 'b -> 'c) -> 'c - let fun x0 z = z in let val x1 = pair x0 x0 in let val x2 = pair x1 x1 in x2 end end end; val it = fn : (((('a -> 'a) -> ('b -> 'b) -> 'c) -> 'c) -> ((('d -> 'd) -> ('e -> 'e) -> 'f) -> 'f) -> 'g) -> 'g ---------------- ---------------- -let fun x1 y = pair y y in let fun x2 y = x1(x1(y)) in x2 (fn z => z) end end; val it = fn : (((('a -> 'a) -> ('a -> 'a) -> 'b) -> 'b) -> ((('a -> 'a) -> ('a -> 'a) -> 'b) -> 'b) -> 'c) -> 'c ----------------