[Haskell-cafe] Why doesn't this work?

Sebastian Sylvan sebastian.sylvan at gmail.com
Mon Apr 25 05:40:41 EDT 2005


On 4/25/05, Michael Vanier <mvanier at cs.caltech.edu> wrote:
> 
> 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


More information about the Haskell-Cafe mailing list