- fun product [] : int = 1 | product (fst::rest) = fst * (product rest);Can also use integers in patterns:
- fun oneTo 0 = [] = | oneTo n = n::(oneTo (n-1)); - fun fact n = product (oneTo n);Note oneTo 5 = [5,4,3,2,1]
Could have written
val fact = product o oneTo (* o is fun. comp. *)
Here is how we could define a reverse fun 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
hd : ('a list) -> 'a tl : ('a list) -> ('a list)Define
fun last [x] = x | last (fst::snd::rest) = last (snd::rest);has type 'a list -> 'a, but don't have to declare it!
Also need to distinguish "equality" types:
- fun search item [] = false = | search item (fst::rest) = if item = fst then true = else search item rest; > val search = fn : ''a -> ((''a list) -> bool)Double quote before variable name indicates "equality" type. Cannot use "=" on types which are function types or contain function types.
- val x = 3 * 3; > val x = 9 : int; - 2 * x; > val it = 18 : intCan also give local declarations of function and variables.
- fun roots (a,b,c) = = let val disc = sqrt (b * b - 4.0 * a * c) = in = ((~b + disc)/(2.0*a),(~b - disc)/(2.0*a)) = end;Static scoping (unlike original LISP)- roots (1.0,5.0,6.0); > (~2.0,~3.0) : real * real - disc;
Type checking error in: disc Unbound 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;What is answer? 3!!
Why? Because definition of f used first "x", not second.
ML employs "eager" or call-by-value parameter passing
Order of operations:
Can have sequential or parallel declarations:- 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 : intHowever, when defining functions, simultaneous declaration supports mutual recursion.
- fun f n = if n = 0 then 1 else g n = and g m = m * f(m-1);
Print every other element in a list:
fun
take (L) =
if L = nil then nil
else hd(L) :: skip(tl(L))
and
skip (L) =
if L = nil then nil
else take(tl(L)) ;
Standard function to calculate the lenght of a list
fun length (nil) = 0
| length (x :: xs) = 1 + length xs;
The list member function
fun member (X, nil) = false
| member (X, x::xs) =
if (X = x)
then true
else member (X, xs) ;
What do these functions do?
fun index(0, h::t) = h
| index(n, h::t) = index(n-1, t);
fun takeN(0, h::t) = nil
| takeN(n, h::t) = h :: takeN(n-1, t);
fun dropN(0, x) = x
| dropN(n, h::t) = dropN(n-1,t);