Building on my previous answer I would suggest implementing sum:
val sum = foldr (op +) 0;
Copying the alternate function from that answer here for completeness, with a small bugfix:
fun alternate l =
let
fun alternate1 [] = []
| alternate1 (x::xs) = x :: alternate2 xs
and alternate2 [] = []
| alternate2 (x::xs) = (~x) :: alternate1 xs
in
alternate1 l
end
Then you can define alternate_sum quite simply:
val alternate_sum = sum o alternate
There will of course be objections in the name of performance. Haskell is able to perform deforestation/fusion optimizations across these sorts of invocations because it knows something about the purity of the functions; Standard ML does not require these optimizations though some implementations may attempt them, I don't know.
The overhead on this particular problem may or may not be absurd, but I think it's a good example of functional programming principles regardless: building up complex behavior from simpler, unimpeachable behavior. The "burden of proof" in this version is almost all on alternate. @SunsetRider's version is fine (it will probably perform better) but the code is more "monolithic" you might say.
Also, @SunsetRider's code is a little more complex than it needs to be, this version is sufficient:
fun alternate l =
let
fun alt([], count) = 0
| alt(x::xs, count) =
if count mod 2 = 0 then x + alt(xs, count+1)
else (~x) + alt(xs, count+1)
in
alt(l, 0)
end
One comment in addition to what @SunsetRider said: in general, in functional languages x = x + 1 and other mutations are a bit of a code smell. You can see that in their code they use count+1 several times instead. Thinking functionally, what matters is what expressions are evaluating to, not the state of variables, so the values that are passed around are critical. This goes back to the superb definition at the beginning of the excellent and hugely underrated book Functional C by Pieter Hartel:
The functional and imperative paradigms operate from different viewpoints. The functional paradigm is based on the evaluation of expressions and binding variables to values. The basic program phrase is the expression, the purpose of evaluating an expression is to produce a value. The order in which subexpressions are evaluated does not affect the resulting value.
The imperative paradigm is based on the execution of statements and having a store where the statements can leave their results. The basic program phrase is the statement; the purpose of executing a statement is to change the store. The order in which statements are executed does affect the resulting values in the store. The current set of values in the store is referred to as the state of the program.