Take the 2-minute tour ×

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
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 ?


share|improve this question

1 Answer 1

up vote 5 down vote accepted

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.

share|improve this answer

Your Answer


