Typeds
Typeds
Typeds
Kathleen Fisher
Examples Non-examples
Integer 3, True, \x->x
String Even integers
Int Bool f:Int Int | if x>3
(Int Int) Bool then f(x) > x *(x+1)
Support optimization
Example: short integers require fewer bits
Access record component by known offset
JavaScript and Lisp use run-time type checking
f(x) Make sure f is a function before calling f.
Basic tradeoff
Both kinds of checking prevent type errors.
Run-time checking slows down execution.
Compile-time checking restricts program flexibility.
JavaScript array: elements can have different types
Haskell list: all elements must have same type
Which gives better programmer diagnostics?
In JavaScript, we can write a function like
function f(x) { return x < 10 ? x : x(); }
Some uses will produce type error, some will not.
Type inference:
int f(int x) { return x+1; };
int g(int y) { return f(y+1)*2;};
Examine code without type information. Infer
the most general types that could have been
declared.
ML and Haskell are designed to make type inference feasible.
Types and type checking
Improved steadily since Algol 60
Eliminated sources of unsoundness.
Become substantially more expressive.
Important for modularity, reliability and compilation
Type inference
Reduces syntactic overhead of expressive types
Guaranteed to produce most general type.
Widely regarded as important language innovation
Illustrative example of a flow-insensitive static
analysis algorithm
Original type inference algorithm was invented by Haskell
Curry and Robert Feys for the simply typed lambda calculus in
1958.
@ t (s = intt)
Possible applications
-fun add(x) = 2+x; -fun isEven(x) = ...;
>val it = fn:int int >val it = fn:int bool
-f(add); -f(isEven);
>val it = 4 : int >val it = true : bool
Function
-fun f(g) = g(2);
>val it = fn:(int t) t
Incorrect use
-fun not(x) = if x then false else true;
>val it = fn : bool bool
-f(not);
Error: operator and operand don't agree
operator domain: int -> 'Z
operand: bool -> bool
g :s x :t
Solve by substitution
Datatype with type variable
- datatype ‘a list = nil | cons of ‘a *(‘a list)
> nil : ‘a list
> cons : ‘a *(‘a list) ‘a list
Polymorphic function
- fun length nil = 0
| length (cons(x,rest)) = 1 + length(rest)
> length : ‘a list int
Type inference
Infer separate type for each clause
Combine by making two types equal (if necessary)
length(cons(x,rest)) = 1 + length(rest)
: p (p = v w, p = t)
(‘a* ‘a list ‘a list = : w (int int = r w)
s * u v) @
@ :v
@ : r (t = u r)
:s*u @ : int int
cons
: ‘a * ‘a list rest : u
length
‘a list + 1 :t
: int
x:s
length(cons(x,rest)) = 1 + length(rest)
Collected Constraints:
:p
p=t
:w p=vw
@
:v
@
:r int int = r w
@
:s*u @ : int int t=ur
cons
: ‘a * ‘a list rest : u ‘a* ‘a list ‘a list =
length
‘a list s*uv
+ 1 :t
: int
x:s
length(cons(x,rest)) = 1 + length(rest)
Collected Constraints:
:p
p=t
:w p=vw
@
:v
@
:r int int = r w
@
:s*u @ : int int t=ur
cons
: ‘a * ‘a list rest : u ‘a = s
length
‘a list + 1 :t ‘a list = u
: int
x:s ‘a list = v
length(cons(x,rest)) = 1 + length(rest)
Collected Constraints:
:p
p=t
:w p = ‘a list w
@
:v
@
:r int int = r w
@
:s*u @ : int int t = ‘a list r
cons
: ‘a * ‘a list rest : u
length
‘a list + 1 :t
: int
x:s
length(cons(x,rest)) = 1 + length(rest)
Collected Constraints:
:p
p=t
:w p = ‘a list int
@
:v
@
:r t = ‘a list int
@
:s*u @ : int int
cons
: ‘a * ‘a list rest : u
length
‘a list + 1 :t
: int
x:s Result:
p = ‘a list int
Function with multiple clauses
- fun append(nil,l) = l
| append(x::xs,l) = x :: append(xs,l)
> append: ‘a list * ‘a list int
Some costs
More difficult to identify program line that causes error
ML requires different syntax for integer 3, real 3.0.
Natural implementation requires uniform representation sizes.
Complications regarding assignment took years to work out.
C++
template <typename T>
void swap(T& x, T& y){
T tmp = x; x=y; y=tmp;
}
Declarations look similar, but compiled very differently
ML
Swap is compiled into one function
Typechecker determines how function can be used
C++
Swap is compiled into linkable format
Linker duplicates code for each type of use
Overloading
A single symbol may refer to more than one
algorithm
Each algorithm may have different type
Choice of algorithm determined by type context
Types of symbol may be arbitrarily different
+ has types int*intint, real*realreal, no
others
Some predefined operators are overloaded
User-defined functions must have unique type
- fun plus(x,y) = x+y;
This is compiled to int or real function, not both