
randomIO needs the unsafePerformIO hack because it does not return the seed... however it can be rewritten: getRandomIO :: Int -> IO (IO Int) getRandomIO x_init = do x <- newIORef x_init return (randomIO x) where randomIO :: IORef Int -> IO Int randomIO r = do -- where f & g generate the pseudo-random sequence x <- readIORef r writeIORef r (f x) return (g x) The difference is in the API to use this version you would have to pass the generator around: main :: IO () main = do rio <- getRandomIO test rio test :: IO Int -> IO () test rio = do x <- rio putStrLn (show x) with randomIO the seed is in a 'global' variable... of course if you want a sequence outside of the IO monad... both versions can be used to generate a lazy sequence... getRandomList :: IO Int -> IO [Int] getRandomList rio = do r0 <- rio rs <- getRandomList rio return (r0:rs) Keean. Graham Klyne wrote:
Looking at the wiki summary [1] (very good, BTW), I have a question (I've skipped much of the debate, so please just give a message pointer if I missed something).
Why does RandomIO need to use the unsafePerformIO hack if its already in the IO monad?
BTW, if the goal is to have a random number generator as a pure (non-IO) function, I *do* think there's a reasonable semantic objection here.
I'd also like to request that some reference links are added for some of the proposed solutions: 2b - reference to stToIO 3 - reference to Data.Dynamic, and how a dictionary of types can be used to provide global variables.
#g --
[1] http://haskell.org/hawiki/GlobalMutableState
------------ Graham Klyne For email: http://www.ninebynine.org/#Contact
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe