Given a list of numbers , I want to create a new list where the element at index i
is the sum of all the i-1
elements before .
For example :
[1,4,6,9] -> [1,5,11,20]
I've written the following code :
fun sum nil = 0
| sum [x]=x
| sum(x::rest)=(x+hd(rest))::sum(rest);
but I got this :
- fun sum nil = 0
= | sum [x]=x
= | sum(x::rest)=(x+hd(rest))::sum(rest);
stdIn:306.16-306.39 Error: operator and operand don't agree [literal]
operator domain: int * int list
operand: int * int
in expression:
x + hd rest :: sum rest
I can see that the recursive rule of (x+hd(rest))::sum(rest);
is the reason for
the problem , but how can I fix it ?
Regards
Look at your base cases. You want the function to return a list, so the base cases should return lists.
fun sum [] = []
| sum [x] = [x]
| sum (x::xs) = ...
I replaced nil
with []
because I like it better - it doesn't really matter.
Another thing - never use the hd
and tl
operators (there are exceptions, but for now, just don't). Sure, in your function, it won't become a problem because you took care of the case where it would, but there's another reason. If you do this:
fun foo [] = ...
| foo (x::y::xs) = ...
SML will tell you that the pattern matching is not exhaustive, that is, there are patterns you've missed, which means you catch the error at compile-time and not at run-time.
Here's a version of your function that works.
fun sum [] = []
| sum [x] = [x]
| sum (x::y::xs) = x::sum (x+y::xs)
I moved the addition to the recursive call because if you add as the first thing, then the first element of the result will be the first two elements of the original list added together.