| Elements of ML Programming, 2nd Edition (ML97) |
fun cube(x:real) = x*x*x;
fun third(L) = hd(tl(tl(L)));
fun thirdChar(s) = third(explode(s));
fun minMax(a,b,c) =
if a<b then
if b<c then (a,c)
else (* b is largest *)
if a<c then (a,b) else (c,b)
else (* a >= b *)
if a<c then (b,c)
else (* a is largest *)
if b<c then (b,a) else (c,a);
fun fact(n) =
if n<=1 then 1 else n*fact(n-1);
fun duplicate(L) =
if L=nil then nil else hd(L)::hd(L)::duplicate(tl(L));
fun maxList(L: string list) = if tl(L)=nil (* L is a single element *) then hd(L) (* the single element is the maximum *) else (* assume there are at least 2 elements *) if hd(L)>hd(tl(L)) (* the first element exceeds the second *) then maxList(hd(L)::tl(tl(L))) (* eliminate second element *) else maxList(tl(L)) (* eliminate first element *);Download this program
There are considerably simpler ways to solve this problem if we use the let-construct described in Section 3.4.
fun fact(1) = 1
| fact(n) = n*fact(n-1);
fun duplicate(nil) = nil
| duplicate(x::xs) = x::x::duplicate(xs);
fun maxList([x:real]) = x
| maxList(x::y::zs) =
if x<y then maxList(y::zs)
else maxList(x::zs);
fun square(0) = 0
| square(n) = square(n-1)+2*n-1;
fun flip(nil) = nil
| flip((x as (a:int,b))::xs) =
if a<b then x::flip(xs) else (b,a)::flip(xs);
fun member(_,nil) = false
| member(x,y::ys) =
(x=y orelse member(x,ys));
We might be tempted to replace the second line by
| member(x,x::xs) = true
| member(x,_::xs) = member(x,xs);
However, it is not permitted to use an identifier like x twice in
one pattern.
fun insert(x,nil) = [x]
| insert(x,S as y::ys) =
if x=y then S else y::insert(x,ys);
fun insertAll(a,nil) = nil
| insertAll(a,L::Ls) = (a::L)::insertAll(a,Ls);
The idea behind the second line is that we put a on the front of
the first list, and then in the recursive call put a on the front
of the remaining lists.
fun powerSet(nil) = [nil]
| powerSet(x::xs) =
powerSet(xs)@insertAll(x,powerSet(xs));
The function above computes the power set as follows.
For a basis, the power set of the empty set is the set containing the
empty set.
The latter is represented by the list [nil], as in the first line
of function powerSet above.
If the given list is not empty, we take the first element x,
compute the power set of the remaining elements, and concatenate this
list with the list of all sets with x added.
Thus, all the sets that have x and those that do not are included in
the overall list.
Incidentally, there is a better way to write this function that does not
require us to compute powerSet(xs) twice.
However, we do not discuss the needed
construct, the ``let''-expression, until Section 3.4.
fun prodDiff1(_,nil) = 1.0
| prodDiff1(a,b::bs) = (a-b)*prodDiff1(a,bs);
fun prodDiff(nil) = 1.0
| prodDiff(b::bs) = prodDiff1(b,bs)*prodDiff(bs);
fun emptyList(nil) = true
| emptyList(_) = false;
fun thousandthPower(x:real) =
let
val x = x*x*x*x*x;
val x = x*x*x*x*x;
val x = x*x*x*x*x
in
x*x*x*x*x*x*x*x
end;
Download this program
fun powerSet(nil) = [nil]
| powerSet(x::xs) =
let
val L = powerSet(xs)
in
L @ insertAll(x,L)
end;
Download the complete program
fun doubleExp(x:real,0) = x
| doubleExp(x,i) =
let
val y = doubleExp(x,i-1)
in
y*y
end;
Note that we could have written the recursive case simply as
| doubleExp(x,i) = doubleExp(x,i-1) * doubleExp(x,i-1);
However, it would take considerably more time to compute the function
this way, as computations would then be repeated an exponential number
of times.
fun cat(nil,M) = M
| cat(x::xs,M) = x::cat(xs,M);
That is, we recursively put the tail of L in front of M,
and finally put the head of L in front of all, using the cons
operator.
fun polyFromRoots(nil) = [1.0]
| polyFromRoots(p::ps) =
pmult([~p,1.0],polyFromRoots(ps));