[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