140 likes | 323 Views
Type Checking and Type Inference. Motivation. Application Programmers Reliability Logical and typographical errors manifest themselves as type errors that can be caught mechanically, thereby increasing our confidence in the code execution. Language Implementers
E N D
Motivation • Application Programmers • Reliability • Logical and typographical errors manifest themselves as type errors that can be caught mechanically, thereby increasing our confidence in the code execution. • Language Implementers • Storage Allocation (temporaries) • Generating coercion code • Optimizations L3Type
Typeless Assembly language Any instruction can be run on any data “bit pattern” Implicit typing and coercion FORTRAN Explicit type declarations Pascal Type equivalence Weak typing C Arrays (bounds not checked), Union type Actuals not checked against formals. Data Abstraction Ada Type is independent of representation details. Generic Types Ada Compile-time facility for “container” classes. Reduces source code duplication. Evolution of Type System L3Type
Languages • Strongly typed (“Type errors always caught.”) • Statically typed (e.g., ML, Ada, Eiffel, etc) • Compile-time type checking : Efficient. • Dynamically typed (e.g., Scheme, Smalltalk, etc) • Run-time type checking : Flexible. • Weakly typed (e.g., C) • Unreliable Casts (int to/from pointer). • Object-Oriented Languages such as Eiffel, Java, etc impose restrictions that guarantee type safety and efficiency, but bind the code to function names at run-time. L3Type
Type inference is abstract interpretation. ( 1 + 4 ) / 2.5 int * int -> int 5 / 2.5 (ML-error) real * real -> real 2.0 ( int + int ) / real int / real real L3Type
Expression Grammar: Type Inference Example E -> E + E | E * E | x | y | i | j • Arithmetic Evaluation x, y in {…, -1.1, …, 2.3, …} i, j in {…, -1,0,1,…} +, * : “infinite table” • Type Inference x, y : real i, j : int L3Type
Values can be abstracted as type names and arithmetic operations can be abstracted as operations on these type names. L3Type
Type correctness is neither necessary nor sufficient for programs to run. if true then 5 else 0.5 • Not type correct, but runs fine. if true then 1.0/0.0 else 3.5 • Type correct, but causes run-time error. L3Type
Assigning types to expressions • Uniquely determined fn s => s ^ “.\n”; val it = fn : string -> string • Over-constrained (type error) (2.5 + 2) • Under-constrained • Overloading fn x => fn y => x + y; (*resolvable *) fn record => #name(record); (* error *) • Polymorphism fn x => 1 ; val it = fn : 'a -> int L3Type
Type Signatures • fun rdivc x y = x / y rdivc : real -> real -> real • fun rdivu (x,y) = x / y rdivu : real * real -> real • fun plusi x y = x + y plusi : int -> int -> int • fun plusr (x:real,y) = x + y plusr : real * real -> real L3Type
Polymorphic Types • Semantics of operations on data structures such as stacks, queues, lists, tables, etc are independent of the component type. • Polymorphic type system provides a natural representation of generic data structures without sacrificing type safety. • Polymorphism fun I x = x; I 5; I “x”; • for all typesa: I: a -> a L3Type
Composition val h = f o g; fun comp f g = let fun h x = f (g x) in h; “Scope vs Lifetime : Closure” comp: (a -> b) -> (l->a) -> (l->b) • Generality • Equality constraints L3Type
map-function fun map f [] = [] | map f (x::xs) = f x :: map f xs map: (a -> b) -> (a list) -> (b list) map (fn x => 0) [1, 2, 3] map (fn x => x::[]) [“a”, “b”] • list patterns; term matching. • definition by cases; ordering of rules L3Type
Conventions • Function application is left-associative. f g h = ( ( f g ) h ) • ->is right-associative. int->real->bool = int->(real->bool) • :: isright-associative. a::b::c::[] = a::(b::(c::[]) • Function application binds stronger than ::. f x :: xs = ( f x ) :: xs (a -> b) -> (b -> c)=/= (a -> b -> b -> c) L3Type