(* run with mosml or smlnj *)
(* simple expressions *)
(3 + 5) * 2;
[(3,4),(5,6)];
if true then 3 else 4;
(* declarations *)
val
a = 3 and
b = 5 and
c = 2;
(a + b) div c;
(* functions *)
val f = fn x => x + 1;
val g = fn (a,b) => (a + b) div 2;
val gp = fn (a,b) => (a + b) / 2.0;
(f 3, g(8,4));
(f, f 3);
val h = g;
(* static scope, deep binding *)
val f = fn x => a + x;
val a = [1,2,3];
f 1;
let
val a = 3 and b = 5
in
(a + b) div 2
end;
(* equivalently: *)
(fn (a,b) => (a + b) div 2) (3, 5);
(* lists *)
nil;
1 :: [2,3];
1 :: 2 :: 3 :: nil;
null [];
null[1,2,3];
hd [1,2,3];
tl [1,2,3];
[1,2] @ [];
[] @ [3,4];
[1,2] @ [3,4];
(* functions *)
val plus = fn (a,b) => a + b;
let
val x = (3,4)
in
plus x
end;
val plus = fn x =>
let
val (a,b) = x
in
a + b
end;
(* "let" is syntactic sugar for immediate application of an anonymous function
let
a = exp
in
body
end;
means the same thing as
(fn a => body) exp
*)
(fn x => plus x) (3, 4);
(* with patterns *)
val f = fn [x,y,z] => (x,y,z);
(* why is this pattern not exhaustive? *)
val (a,b,c) = f[1,2,3];
val f = fn [x,y,z] => (x,y,z)
| [x,y] => (x,y,0)
| [x] => (x,0,0)
| [] => (0,0,0)
| x :: y :: z :: _ => (z,y,x) ;
(* recursive functions *)
val rec factorial = fn n =>
if n = 0 then
1
else
n * factorial(n-1);
factorial 0;
factorial 6;
factorial ~3;
(* case analysis in functions *)
val rec summation =
fn nil => 0
| (head :: tail) =>
head + summation tail;
summation nil;
summation [1,2];
(* polymorphic with type identifier *)
val rec length =
fn nil => 0
| (_ :: tail) =>
1 + length tail;
(length [1,2,3], length ["a","b","c","d"]);
val swap = fn (x,y) => (y,x);
(* list functions are polymorphic *)
nil;
null;
hd;
tl;
(* higher order functions *)
val times = fn a => (fn b => a * b);
times 3 4;
val twice = times 2;
twice 4;
val comp = fn (f,g) => (fn x => f (g x));
val fourtimes = comp(twice,twice);
fourtimes 5;
(* currying *)
val plus = fn (a, b) => a + b: int;
val curry = fn f => fn a => fn b => f(a,b);
val curryplus = curry plus;
val successor = curryplus 1;
curryplus 3;
curryplus 3 4;
successor 12;
(* datatypes *)
datatype money =
nomoney |
coin of int |
bill of int |
check of string * int;
val plusm = fn (coin a, coin b) => coin (a+b)
| (bill a, bill b) => bill (a+b)
| (nomoney, x) => x
| (x, nomoney) => x
| (check (s, a), check(t, b)) => check (s, a+b)
| (_, _) => nomoney
;
val
nickel = coin 5 and
dime = coin 10 and
quarter = coin 25;
fun
amount nomoney = 0 |
amount (coin cents) = cents |
amount (bill dollars) = 100 * dollars |
amount (check(bank,cents)) = cents;
(* a single type constructor has the same name as datatype by convention *)
datatype point = point of int * int;
(* polymorphic datatypes *)
datatype 'a predicate =
predicate of 'a -> bool;
datatype ('a,'b) leftprojection =
leftprojection of ('a * 'b) -> 'a;
(* recursive datatypes *)
datatype 'a myList =
empty |
cons of 'a * 'a myList;
val head = fn cons (a,rest) => a;
val tail = fn cons (a,rest) => rest;
val rec last = fn cons(a, empty) => a
| cons(a, something) => last(something) ;
(* vim: nospell:filetype=sml
*)