
On 4/25/05, Michael Vanier
I've been trying to generate an infinite list of random coin flips in GHC 6.4, and I've come across some strange behavior:
---------------------------------------------------------------------- import System.Random
data Coin = H | T deriving (Eq, Show)
-- Generate a random coin flip. coinFlip :: IO Coin coinFlip = do b <- getStdRandom random return (bool2coin b) where bool2coin True = H bool2coin False = T
-- Generate an infinite list of coin flips. coinFlips :: IO [Coin] coinFlips = sequence cfs where cfs = (coinFlip : cfs)
-- Print n of them. test :: Int -> IO () test n = do f <- coinFlips print (take n f) ----------------------------------------------------------------------
Now when I do "test 1" (for instance), it hangs forever. It seems as if there is some kind of strictness constraint going on that I don't understand. My understanding is that cfs is an infinite list of (IO Coin), sequence lifts this to be IO [Coin] where [Coin] is an infinite list, and then test should extract the infinite list of coin flips into f, take some number of them, and print them. But instead, the system appears to be trying to compute all the coin flips before taking any of them. Why is this, and how do I fix it?
I think you're doing too much in the IO monad and sequence introduces unwanted strictness. Try this instead: coins :: RandomGen g => g -> [Coin] coins g = map bool2coin (randoms g) where bool2coin True = H bool2coin False = T coinFlips :: IO [Coin] coinFlips = do g <- newStdGen return (coins g) test :: Int -> IO () test n = do f <- coinFlips print (take n f) Basically: Don't do stuff in the IO monad unless it really belongs in the IO monad. /S -- Sebastian Sylvan +46(0)736-818655 UIN: 44640862