(* Always include these at the top of your SML files so
large datatype values and lists will print fully *)
Control.Print.printDepth := 100;
Control.Print.printLength := 100;
(*
Partition: int * int list -> int list * int list
Partition list around the pivot, and return the lists
of smaller and larger elements.
*)
fun partition (pivot, nil) = (nil, nil)
| partition (pivot, x::xs) =
let
val (smaller, bigger) = partition (pivot, xs)
in
if x < pivot then (x::smaller, bigger)
else (smaller, x::bigger)
end;
(*
qsort: int list -> int list
Sort a list of integers using quick sort.
*)
fun qsort (nil) = nil
| qsort (p::rest) =
let
val (smaller, bigger) = partition(p,rest)
in
qsort(smaller) @ [p] @ qsort(bigger)
end;
qsort [6,23,6,3,78,23,12,6,7,34,7,1,23,7,23,6,3,6];
(* Always include these at the top of your SML files so
large datatype values and lists will print fully *)
Control.Print.printDepth := 100;
Control.Print.printLength := 100;
(*
partition: (('a * 'a -> bool) * 'a * 'a list)
-> ('a list * 'a list)
In this version, you must supply a lessThan fuction for
comparing values -- note the intended type is above, though
inference gives you a slightly more general type...
*)
fun partition (lessThan, pivot, nil) = (nil, nil)
| partition (lessThan, pivot, x::xs) =
let val (smaller, bigger) = partition(lessThan, pivot, xs)
in
if lessThan(x,pivot) then (x::smaller, bigger)
else (smaller, x::bigger)
end;
(* qsort: ('a * 'a -> bool) * 'a list -> 'a list *)
fun qsort (lessThan, nil) = nil
| qsort (lessThan, p::rest) =
let val (smaller, bigger) = partition(lessThan, p,rest)
in
qsort (lessThan, smaller) @ [p] @ qsort(lessThan, bigger)
end;
qsort (op<, [6,23,6,3,78,23,12,6,7,34,7]);
qsort (fn (x,y) => (size(x) < size(y)), ["1","4 cows","~12"]);
(*
* contains: ''a * ''a list -> bool
* This function illustates equality types.
*)
fun contains(x, nil) = false
| contains(x, y::ys) =
x = y orelse contains(x,ys);
contains(1, [1,2,3]);
contains("cow", ["moo", "moo"]);
contains(2.3, [0.1, 0.2]); (* BAD -- reals do not admit equality *)
(*
Create a simple abbreviation for the tupe type int * int
*)
type Point = int * int;
val x : Point = (3,4);
Java constants:
public static final int NORTH = 1;
public static final int SOUTH = 2;
public static final int EAST = 3;
public static final int WEST = 4;
public move(int x, int y, int dir) {
switch (dir) {
case NORTH: ...
case ...
}
}
ML datatype:
(*
A datatype declaration that creates a new type
to represent the compass directions.
*)
datatype Direction = North | South | East | West;
(*
move: (int * int) * Direction -> (int * int)
A function to move a point in the specified direction
on the Cartesian plane.
*)
fun move((x,y),North) = (x,y+1)
| move((x,y),South) = (x,y-1)
| move((x,y),East) = (x+1,y)
| move((x,y),West) = (x-1,y);
val dir = West;
move ((1,2), dir);
move ((0,0), North);
(*
A datatype to represent members of a cow herd.
Calves keep (id, weight).
Milkers keep (name, milk per day, weight).
*)
datatype Cow = Calf of int * int
| Milker of string * real * int;
(*
weight : Cow -> int
Return the weight of a cow in lbs.
*)
fun weight (Calf(id,lbs)) = lbs
| weight (Milker(name,amt,lbs)) = lbs;
(*
milk : Cow -> real
Return the average daily milk production of a cow in gallons.
*)
fun milk (Calf(_,_)) = 0.0
| milk (Milker(_,amt,_)) = amt;
(*
milk : Cow list -> real
Return the average daily milk production for a list of cows.
*)
fun production (nil) = 0.0
| production (x::xs) = milk(x) + production(xs);
(* Some specific cows *)
val springer = Milker("Springer", 3.4, 1100);
val radish = Calf(1604, 95);
val herd = [springer, radish, Milker("Clementine", 5.1, 750)];
weight(springer);
weight(radish);
milk(springer);
production(herd);
(*
Another Datatype Example...
A datatype to represent two different payment schemes.
*)
datatype Payment = Cash of real
| Check of string * int * real;
(*
amount : Payment -> double
Return the amount of either kind of payment
*)
fun amount (Cash(x)) = x
| amount (Check(bank,num,x)) = x;
(*
isCheck : Payment -> boolean
Return whether a payment is a check.
*)
fun isCheck (Cash(_)) = false
| isCheck (Check(_,_,_)) = true;
(*
tally : Payment list -> real
Sum the amounts of all payments in a list
*)
fun tally nil = 0.0
| tally (p::ps) = amount(p) + tally(ps);
val p1 = Cash(100.00);
val p2 = Check("BankNorth", 1001, 55.55);
amount(p1);
amount(p2);
isCheck(p1);
isCheck(p2);
tally [p1,p2];
(*
A recursive datatype to capture simple parse trees
for expressions.
*)
datatype Expr = Num of int
| Plus of Expr * Expr
| Mult of Expr * Expr
;
(*
eval : Expr -> int
Compute the value of an expression represented as
an Expr.
*)
fun eval(Num(n)) = n
| eval(Plus(e1,e2)) = eval(e1) + eval(e2)
| eval(Mult(e1,e2)) = eval(e1) * eval(e2)
;
val e1 = Plus(Num(1), Mult(Num(2),Num(3)));
eval e1;
(*
A polymorphic recursive datatype to represent trees
containing any type of value in the nodes.
*)
datatype 'a Tree = Empty
| Node of 'a * 'a Tree * 'a Tree;
(* create an int Tree and a string Tree *)
val iTree = Node(3, Node(1,Empty,Empty), Node(2,Empty,Empty));
val sTree = Node("A", Node("B",Empty,Empty), Node("C",Empty,Empty));
(*
flatten: 'a Tree -> 'a list
Return a list of all values stored in a tree.
*)
fun flatten (Empty) = nil
| flatten (Node(v,l,r)) = flatten(l) @ [v] @ flatten(r);
flatten iTree;
flatten sTree;