I have a simple problem: given a list of integers, read the first line as N. Then read the next N lines and return their sum. Repeat to N= 0.
My first approach used this:
main = interact $ unlines . f . (map read) . lines
f::[Int] -> [String]
f (n:ls)
| n == 0 = []
| otherwise = [show rr] ++ (f rest)
where (xs, rest) = splitAt n ls
rr = sum xs
f _ = []
But it is relatively slow. I profiled it with
ghc -O2 --make test.hs -prof -auto-all -caf-all -fforce-recomp -rtsopts
time ./test +RTS -hc -p -i0.001 < input.in
Where input.inis the test input, where the first line is 100k, followed by 100k random numbers, followed by 0. We can see in the figure below that it uses O (N) memory:

EDITED . My initial question was comparing two similar slow approaches. I updated it to compare with the optimized approach below
Now, if I do the sum iteratively, instead of calling sum, I get a constant amount of memory
{-
main = interact $ unlines . g . (map read) . lines
g::[Int] -> [String]
g (n:ls)
| n == 0 = []
| otherwise = g' n ls 0
g _ = []
g' n (l:ls) !cnt
| n == 0 = [show cnt] ++ (g (l:ls))
| otherwise = g' (n-1) ls (cnt + l)

, . , ?