Write a function min_max : int list -> int * int
that takes a non-empty list of numbers, and returns a pair (min, max) of the minimum and maximum of the numbers in the list.
Here is what I've written so far.
fun min_max (n : int list) =
if null n then NONE
else
let
fun max (n : int list) =
if null (tl n) then hd n
else
let
val mn = max (tl n)
in
if hd n > mn then hd n
else mn
end
fun min (n : int list) =
if null (tl n) then hd n
else
let
val mix = min (tl n)
in
if hd n < mix then hd n
else mix
end
in
SOME (min :: max)
end;
Most of what you've written works. Your min
and max
functions work.
SOME (min :: max)
This doesn't work, though.
This is not how you construct a "pair" or "tuple" of values. Rather:
SOME (min, max)
Moreover, this is now just two functions. You need to apply those functions to your list n
to get the results you're looking for.
SOME (min n, max n)
As a suggestion, you can use pattern-matching to simplify your code considerably by avoiding hd
and tl
and replacing the conditional test on the tail. For instance:
fun min([n]) = n
| min(h::t) =
let
val m = min(t)
in
if h < m then h
else m
end;
But we know that h::t
represents a list with at least two elements, so we can bind names to those elements in our pattern.
fun min([n]) = n
| min(x::(tl as y::z)) =
if x < y then min(x::z)
else min(tl);
If we evaluate this on a list, we can see how it would proceed.
min([7,8,2,4,6,1,9])
min(7::[2,4,6,1,9])
min([2,4,6,1,9])
min(2::[6,1,9])
min(2::[1,9])
min([1,9])
min(1::[]) -> min([1])
1
This also has the benefit of being tail-recursive.