
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

Thanks to everyone for replying. Things make more sense now (I've re-read a chunk of the Haskell Companion that really hammers home the difference between actions and monads). Also, thanks for the pointer to random numbers without IO - I'd actually written my own equivalent, but will now drop it and use that. Cheers, Andrew On Sat, Feb 17, 2001 at 03:27:31PM -0500, Scott Turner wrote:
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
participants (2)
-
andrewļ¼ andrewcooke.free-online.co.uk
-
Scott Turner