[newbie] Lazy >>= ?!

Scott Turner p.turner@computer.org
Sat, 17 Feb 2001 15:27:31 -0500


Andrew Cooke wrote:
>1.  After digesting what you wrote I managed to make a lazy list of IO
>monads containing random numbers, but couldn't make an IO monad that
>contained a lazy list of random numbers.  Is this intentional, me
>being stupid, or just chance?

I had wondered what kind of thing you were doing with the IO monad.  Random
numbers are an odd fit.  Pseudorandom numbers can be generated in a lazy
list easily; you don't need a connection with the IO monad to do it.  Using
the Random module of the Hugs distribution, it's for example
         randoms (mkStdGen 1) :: [Int]

The IO monad can be brought into this picture easily.
         return (randoms (mkStdGen 1)) :: IO [Int]

But it sounds as if you're looking for something more sophisticated.  You
want to use randomIO perhaps because it better matches your notion of how
random numbers should be generated.  Using randomIO places more
restrictions on how you operate, because it forces the random numbers to be
created in a particular sequence, in relation to any other IO which the
program performs.  Every random number that is ever accessed must be
produced at a particular point in the sequence.  An unbounded list of such
numbers cannot be returned!  That is, you are looking for
           randomsIO :: IO [a]
which yields a lazy list, by means of repeated calls to randomIO.  All such
calls would have to occur _before_ randomsIO returns, and before _any_ use
of the random numbers could be made.  The program hangs in the process of
making an infinite number of calls to randomIO.

But, you may say, those infinite effects are invisible unless part of the
list is referenced later in the program, so a truly lazy implementation
should be able to skip past that stuff in no time.  Well, that's
conceivable, but (1) that's making some assumptions about the implemetation
of randomIO, and (2) lazy things with no side effects can and should be
handled outside of the IO monad.

>Also, should I be worried about having more than one IO monad - it
>seems odd encapsulating the "outside world" more than once.

No.  Consider the expression 
    sequence_ [print "1", print "two", print "III"]
Try executing it from the Hugs command line, and figure out the type of the
list.  An expression in the IO monad, such as 'print 1' makes contact with
the "outside world" when it executes, but does not take over the entire
outside world, even for the period of time that it's active.

I moved this to haskell-cafe mailing list, because it's getting a little
extended.

--
Scott Turner
p.turner@computer.org       http://www.billygoat.org/pkturner