- Pattern matching
- Type inference
- Polymorphism (including overloading problems)
- Local declarations (including parallel and sequential declarations).
- Examples
- Defining new types

Can also use integers in patterns:- fun product [] : int = 1| product (fst::rest) = fst * (product rest);

Note oneTo 5 = [5,4,3,2,1]- fun oneTo 0 = []= | oneTo n = n::(oneTo (n-1));- fun fact n = product (oneTo n);

*Could have written*

`val fact = product o oneTo (* o is fcn. comp. *)`

Here is how we could define a reverse fcn if it were not provided:

- fun reverse [] = []= | reverse (h::t) = reverse(t)@[h]; (* pattern matching *)

Rarely use `hd` or `tl` - list operators giving head and tail of
list.

Note that `hd (a::x) = a, tl(a::x) = x, `and` ((hd x) :: (tl x)) =
x`
if x is a list with at least one element.

Can use pattern matching in relatively complex ways to bind variables:

- val (x,y) = (5 div 2, 5 mod 2);> val x = 2 : int> val y = 1 : int- val head::tail = [1,2,3];> val head = 1 : int> val tail = [2,3] : int list- val {a = x, b = y} = {b = 3, a = "one"};> val x = "one" : string> val y = 3 : int- val head::_ = [4,5,6]; (* note use of wildcard "_" *)> val head = 4 : int

Thus

Definehd : ('a list) -> 'atl : ('a list) -> ('a list)

has typefun last [x] = x| last (fst::snd::rest) = last (snd::rest);

Also need to distinguish "equality" types:

Double quote before variable name indicates "equality" type. Cannot use "=" on types which are function types or contain function types. Also only type variables allowed in equality types are those with ''.- fun search item [] = false= | search item (fst::rest) = if item = fst then true= else search item rest;> val search = fn : ''a -> ((''a list) -> bool)

Can also give local declarations of function and variables.- val x = 3 * 3;> val x = 9 : int;- 2 * x;> val it = 18 : int

Static scoping (unlike original LISP)-funroots (a,b,c) ==letval disc = sqrt (b * b - 4.0 * a * c)=in= ((~b + disc)/(2.0*a),(~b - disc)/(2.0*a))=end;

- roots (1.0,5.0,6.0);> (~2.0,~3.0) : real * real- disc;

Type checking error in: discUnbound value identifier: disc

- val x = 3;> val x = 3 : int- fun f y = x + y;> val f = fn : int -> int- val x = 6;> val x = 6 : int- f 0;

* Why? Because definition of f used first "x", not second.*

ML employs "eager" or call-by-value parameter passing

Talk later about "lazy" or "call-by-need".

Order of operations:

Can have sequential or parallel declarations:However, when defining functions, simultaneous declaration supports mutual recursion.- val x = 12= val y = x +2;> val x = 12 : int> val y = 14 : int- val x = 2= and y = x + 3;> val x = 2 : int> val y = 15 : int

-funf n =ifn = 0then1elseg n=andg m = m * f(m-1);

Can make polymorphic if pass in less than operator:funpartition (pivot, nil) : int list * int list = (nil,nil)| partition (pivot, first :: others) =letval (smalls, bigs) = partition(pivot, others)iniffirst < pivotthen(first::smalls, bigs)else(smalls, first::bigs)end;(* Must type fcn since uses overloaded "<" *)funqsort nil = nil| qsort [singleton] = [singleton]| qsort (first::rest) =letval (smalls, bigs) = partition(first,rest)inqsort(smalls) @ [first] @ qsort(bigs)end;

Now if define:funpartition (pivot, nil) (lessThan) = (nil,nil)| partition (pivot, first :: others) (lessThan) =letval (smalls, bigs) = partition(pivot, others) (lessThan)inif(lessThan first pivot)then(first::smalls, bigs)else(smalls, first::bigs)end;>valpartition =fn: ('a * ('b list)) ->(('b -> ('a -> bool)) -> (('b list) * ('b list)))funqsort nil lessThan = nil| qsort [singleton] lessThan = [singleton]| qsort (first::rest) lessThan =letval (smalls, bigs) = partition(first,rest) lessThanin(qsort smalls lessThan) @ [first] @ (qsort bigs lessThan)end;>valqsort =fn: ('a list) -> (('a -> ('a -> bool)) -> ('a list))

Note: could define- intLt (x:int) (y:int) = x < y;- qsort [6,3,8,4,7,1] intLt;> val [1,3,4,6,7,8] : int list

but wrong type for what needed here!- val PIntLt :int * int -> bool = op <;

__Ex. Obvious recursive def in ML:__

-funfib 0 : int = 1= | fib 1 = 1= | fib n = fib (n-2) + fib (n-1);

Function fastfib (n:integer):integer; val a,b : integer; begin a := 1; b := 1; while n > 0 do begin a := b; b := a + b; n := n - 1 (* all done in parallel *) end; fib := a end;

fun fastfib n : int = letfun fibLoop a b 0 = a| fibLoop a b n : int = fibLoop b (a+b) (n-1)in fibLoop 1 1 nend;(* Must type result because of overloaded "+" *)

typepoint = int * int (* nullary *)type'a pair = 'a * 'a (* unary *)

Types are disjoint unions (w/constructors as tags)

Support recursive type definitions!

Generative (support pattern matching as well)

"con" stands for constructor.-datatypecolor = Red | Green | Blue;> datatype color = Blue | Green | Redcon Red = Red : colorcon Green = Green : colorcon Blue = Blue : color

Write constructor tags with capital letter as convention to distinguish from variables.

Write binary search program using trees!datatype 'a tree = Niltree | Maketree of 'a * ('a tree) * ('a tree)> datatype 'a tree = Maketree of 'a * ('a tree) * ('a tree) | Niltreecon Niltree = Niltree : 'a treecon Maketree = fn : ('a * ('a tree) * ('a tree)) -> ('a tree)

Can also have any kind of tagged unions:fun insert (new:int) Niltree = Maketree (new,Niltree,Niltree)| insert new (Maketree (root,l,r)) = if new < rootthen Maketree (root,(insert new l),r)else Maketree (root,l,(insert new r))fun buildtree [] = Niltree| buildtree (fst :: rest) = insert fst (buildtree rest)fun find (elt:int) Niltree = false| find elt (Maketree (root,left,right)) =if elt = root then trueelse if elt < root then find elt leftelse find elt right (* elt > root *)fun bsearch elt list = find elt (buildtree list);- buildtree [8,3,6,8,3,4,9,10];> Maketree (10,Maketree (9,Maketree (4,Maketree (3,Niltree, Maketree (3,Niltree,Niltree)),Maketree (8,Maketree (6,Niltree,Niltree),Maketree (8,Niltree,Niltree))),Niltree), Niltree) : int tree- bsearch 4 [8,3,6,8,3,4,9,10];> true : bool- bsearch 7 [8,3,6,8,3,4,9,10];> false : boolfun sumtree Niltree = 0| sumtree (Maketree(root,left,right)) = root + sumtree left + sumtree right;

Worth remarking that updating of data structures based on sharing:- datatype sum = IntTag of int | RealTag of real | ComplexTag of real * real;

Ex.: If define

then get sharing:-funupdatehd newhd (head::tail) = newhd :: tail;

Safe, because list elt's not updateable!

Abstract data types - later