-5

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;
Chris
  • 26,361
  • 5
  • 21
  • 42
Maslo Kar
  • 9
  • 1
  • Hi and welcome to StackOverflow. Please take the time and read through [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). Your post currently does not really have a specific question. Try to narrow down what the problem is or where exactly you are stuck. What is the current result of your code? Also, this pretty much looks like an assignment. You can ask specific questions, but don't expect people here to write the entire solution for you. – Fitzi May 12 '23 at 16:33
  • You don't need the `min` and `max` functions, you can (and are probably expected to) recurse with `min_max` directly. Also, the task says that the input isn't empty and you should return a pair, not an `option`. – molbdnilo May 13 '23 at 08:15

1 Answers1

0

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.

Chris
  • 26,361
  • 5
  • 21
  • 42