Lecture 008

Monomorphism

With Non-greek letters

Polymorphism

Alpha letters ('a, 'b , etc are reserved for generic type.

Lists

datatype 'a list = nil | :: of 'a * 'a list
infix ::

We say: int list is an instance of 'a list

datatype ('a, 'b) either = Left of 'a | Right of 'b
You can't write val y: a' = ...

Another example:

val m = ([], [])
m: 'a list * 'b list

val m = "string":[]
[] is still 'a list but m is string list
we instanciated 'a to string

[] :: [] is 'a list list
because 'b is instanciated to 'a

[] :: [1]
You will get an error
We say: 'a list does not unify with int

Trees

datatype 'a tree = Empty | Node of 'a tree * 'a * 'a tree

(* trav: 'a tree -> 'a list*) a polymorphic function
fun trav (Empty : 'a tree) : 'a list = []
  | trav (Node(l, x, r)) = trav l @ x :: trav r

op@ : 'a list * 'a list -> 'a list

Zip

fun zip([] : 'a list, _ : 'b list) : ('a * 'b) list = []
  | zip(_, []) = []
  | zip(x::xs, y::ys) = (x, y) :: zip(xs, ys)

Option

datatype 'a option = NONE | SOME of 'a

(* lookup : (('a * 'a -> bool) * 'a * 'b list) -> 'b option *)
fun lookup(_, _, []) = NONE
  | lookup(eq, x, (a, b) :: rest) = if
  eq(x, a) then SOME b else lookup (eq, x, rest)

Sample Code

L = [(1, "hi")]
lookup(op=, 1, L) : string option
lookup((fun(x, y) => x=y) 1, L) : string otion
lookup(op=, 2, L) : string option

The type check happens before code run, so NONE has string option as type SML checks expression by finding the most general type that consistent with the constraints. If it is not possible, then ill-typed, and will generate type error.

Real / Int behavior

fun square x = x * x
square: int -> int

fun square x : real = x * x
square: real -> real

If SML can't figure out if it is int or real, make it into int.

fun loop x = loop x
loop: 'a -> 'b (function of this type always loop)

fun id x = x
id: 'a -> 'a (function of this type is either loop or identity)

fun fastloop x = fastloop (fastloop x)
fastloop : 'a -> 'a (loop an fastloop are entential equivalent)

fun twice f = f(f 0)
twice: (int -> int) -> int

((id twice) square) : int
((twice id) square) is ill typed

fun bind (f, SOME x) = f x
  | bind (_, NONE) = NONE
bind: ('a -> 'b option) * 'a option -> 'b option

fun f x = f (0, true)
f: int * bool -> 'a

fun g x = g(x, x) not well typed
g is not well typed, as 'a cannot be unified with 'a * 'a

Table of Content