Strict foldl

Manuel M. T. Chakravarty chak@cse.unsw.edu.au
Fri, 07 Dec 2001 10:34:40 +1100


"Ch. A. Herrmann" <herrmann@infosun.fmi.uni-passau.de> wrote,

> which compiler settings do I have to pass to ghc-5.02
> in order to achieve that the strictness analyzer
> recognizes strictness of (+) in foldl and computes
> sum in constant space?
> 
> Prelude> sum [1..10000000]
> 
> had the following effect:
> 
>   PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
> 23542 herrmann  20   0  250M 130M 97500 R    66.3 52.4   0:21 ghc-5.02

Is this what I think it is?  Do you benchmark the
interpreter?  Interpreted code isn't optimised.  When I
compile 

  main = print $ sum [1..10000000]

with -O2, it takes 13s on a 600MHz P3 and runs in 1.5MB of
space.

Now, you may think that `sum' should have been compiled
optimised in the Prelude and you just call this optimised
version from the interpreter.  However, this reasoning is
flawed for a number of reasons (one being that you won't
make use of specialised versions of Prelude functions in
this way).

> Of course, one could define a strict foldl oneself:
> 
> > sfoldl f e [] = e
> > sfoldl f e (x:xs) = (sfoldl f $! (f e x)) xs
> 
> (  > sfoldl (+) 0 [1..10000000] 
>    returns 50000005000000 in about a minute interpreted 
>    using 18MB of total space.)
> 
> But with the own definition one has to redefine many of the prelude functions.

GHC's Prelude does not define `sum' in terms of foldl;
instead, it uses the definition

  sum :: (Num a) => [a] -> a
  sum l = sum' l 0
    where
      sum' []     a = a
      sum' (x:xs) a = sum' xs (a+x)

The Prelude also defines a specialisation of the function
for `Integer' (which is what you get in your example) by way
of 

  {-# SPECIALISE sum :: [Integer] -> Integer #-}

I haven't checked the Core code produced for the above
definition, but as I know GHC, I am pretty sure that it
compiles the Prelude definition into a nice tight loop
making use of all available strictness.

Cheers,
Manuel