Reputation: 65
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
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