[Haskell-cafe] Generating a random list

Kalman Noel kalman.noel at bluebottle.com
Sat Mar 1 05:52:46 EST 2008


Milos Hasan wrote:
> Here's a minimal summing example that illustrates the difference. The 
> following works fine, since the elements are generated lazily and summed 
> on the fly, as expected:
> 
> randFloats :: [Float]
> randFloats = randoms (mkStdGen 0)
> 
> main = do
>    let xs = take 1000000 randFloats
>    print $ sum xs
> 
> But this overflows, because the list is created before being summed, and 
> the take function goes into awfully deep recursion:
> 
> randFloats :: [Float]
> randFloats = randoms (mkStdGen 0)
> 
> main = do
>    xs <- return $ take 1000000 randFloats
>    print $ sum xs
> 
> Is there a clean way to avoid this problem?

There is, and it has already been mentioned: It's the behaviour of
Prelude.sum that is bugging you. ‘sum’ will build an expression like
this, which is responsible for the stack overflow:

    ((((...(n1 + n2) + n3) + n4) + ...) + nm)
                                        ^ evaluation will start here
               ^ But this is the first addition to be performed

Instead, just use sum', which is defined just like sum, but with a
strict left fold instead of a lazy left fold:

    import Data.List

    sum' :: (Num a) => [a] -> a
    sum' = foldl' (+) 0

I don't know exactly why there is a difference between both programs.  
I suppose that in the first one, the strictness analyzer can optimize
sum into sum', but in the second one it cannot.

Kalman

----------------------------------------------------------------------
Get a free email address with REAL anti-spam protection.
http://www.bluebottle.com/tag/1



More information about the Haskell-Cafe mailing list