NewProgrammer686
NewProgrammer686

Reputation: 65

Standard ML sum function

I have a problem in which I am asked for a function that sums all the elements in a given variable x. For instance, sum([5,5,5]) should return 15.

My troubles come into play when I test the sum of a single integer like this: sum(5)

The function is supposed to be able to go back and fourth between single numbers and a list of numbers. I know that to do this, I need a datatype which has some Int of int | Null | ...

My question is how do I make the code below work for the test case sum(5);

fun sum(x) = if x = nil
             then 0
             else hd(x) + sum(tl(x))

val result = sum([5,5]);

I think I need something like:

else if (int? x) then x
else hd(x) + sum(tl(x))

but when i do this with my datatypes i get clash of int vs int list.

Upvotes: 1

Views: 3947

Answers (1)

sshine
sshine

Reputation: 16105

To answer your question quickly: That is not possible. As you correctly say, you need a datatype that allows you to hold either a single integer, or a list of integers. You could introduce such a type like:

datatype my_int = SingleInt of int | ManyInts of int list

fun sum (SingleInt i) = i
  | sum (ManyInts is) = foldl op+ 0 is

But this is really kind of silly, because if you think about it, the type int list can already hold a single integer or a list of integers (and even zero integers which, when it comes to sum, has a well-defined meaning). Thus, it does not make sense to extend your function beyond handling lists.

And regardless of whether you use a custom type or not, you will not have access to overloading, so being able to write either sum 5 or sum [5,5,5] is not possible in Standard ML. In other functional languages, like Haskell, you can achieve this kind of overloading using type classes.

As a side note, try and use pattern matching rather than if-then-else. Your sum function would be:

fun sum [] = 0
  | sum (x::xs) = x + sum xs

Or making a tail-recursive version:

fun sum xs =
    let fun helper [] result = result
          | helper (x::xs) result = helper xs (x+result)
    in helper xs 0 end

Or simply using folding:

val sum = foldl op+ 0

Upvotes: 2

Related Questions