# [Haskell-cafe] Why doesn't laziness save the day here?

Dale Jordan dalej at alum.mit.edu
Mon Jan 4 20:31:20 EST 2010

```Kind and Generous Haskellers:

I am ensnared in a briar patch of infinite lists and Random gnerators
trying to use laziness to advantage.  Here's my code:

----------------- 8< --------------------
import Control.Applicative
import System.Random.Mersenne.Pure64

-- the generator.  The idea is that the action returns a finite list
-- of random values and iterateR lazily creates an infinite list of
-- values.

iterateR act = do
gen <- get
let (as,gen') = runRand act gen
put \$! gen'
(as ++) <\$> iterateR act

-- A simple example of a finite action
something :: (RandomGen g) => Int -> Int -> Rand g [Int]
something n m = sequence . replicate n \$ getRandomR (m,m+9)

run1 = evalState (take 10 <\$> (iterateR (something 2 0))) \$ pureMT 42

run2 = evalState
(take 10 <\$> (iterateR (something 2 0) >> iterateR (something
3 10)))
\$ pureMT 42

run3 = evalState
(take 10 <\$> (iterateR (something 2 0) >>= iterateR .
\$ pureMT 42
------------------- >8 ----------------------

Evaluating run1 works fine (ghci 10.3):
*Main> run1
[1,9,5,3,6,9,1,5,1,8]

Evaluating run2 or run3 loops and quickly exhausts the heap.

(Using Control.Monad.State.Strict causes stack overflow, though)

The motivation for iterateR is to be able to have the ultimate
consumer determine how many random values to force, but still have a
single random generator used throughout the computation.

My intuition tells me that since the infinite list is produced in
finite batches, the generator shouldn't be tangled up in an infinite
list such as produced by MonadRandom's getRandoms, but I only have a