10

This is what I get in the console:

ghci> sum $ takeWhile (<10000000) [1..]
49999995000000
(11.96 secs, 2174569400 bytes)

That's over 2GB! I would imagine that sum can discard whatever it has already summed. How would you write this?

Gunchars
  • 9,555
  • 3
  • 28
  • 27

2 Answers2

13

You're creating ten million Integers, and a lot of list cells. Also, you're running interpreted code, if you ran it through the compiler, that would reduce the allocation somewhat.

The main problem is that the interpreter doesn't optimise at all, so the sum uses the lazy variant that builds a huge thunk. sum discards the part of the list it has consumed just fine, but it replaces it with a thunk to compute the result afterward, so

sum [1,2,3,4 ...]

becomes

(...((((0 + 1) + 2) + 3) + 4) + ...)

afterward. That's not the optimal substitution, since addition of Integers is strict.

At the ghci prompt, you should write

Prelude Data.List> foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
49999995000000
(1.41 secs, 1443355832 bytes)

to fix that. In a compiled (with optimisations, of course) programme, sum will work fine.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
6

This looks exactly like what's described at http://www.haskell.org/haskellwiki/Memory_leak

So the solution here could be foldl' (+) 0 $ takeWhile (<10000000) [1..] (which needs import Data.List).

There is probably a better solution, since I'm just a Haskell newbie and was curious, too. =^.^= (Edit: please read the first comment below :-P )

  • 7
    "If you are noticing a space leak while running your code within GHCi, please note that interpreted code behaves differently from compiled code: even when using `seq`." - http://www.haskell.org/haskellwiki/Memory_leak – cacba Jan 12 '13 at 23:33