Why does RandomIO need the unsafePerformIO hack? (was: [Haskell-cafe] Top-level state debate on the wiki)

John Meacham john at repetae.net
Fri Dec 3 06:31:31 EST 2004

On Fri, Dec 03, 2004 at 10:05:08AM +0000, 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?

The random number state needs to be stored between calls to randomIO, it
is global state which right now tends to be implemented via the
unsafePerformIO hack. Any of the current global state hacks or the
proposals on the Wiki would also suffice to implement it.

All of the global state proposals would require access to the state via
the IO monad. Which is why I like to think of it as 'extending the
world' rather than global variables. 

IO can be thought of (and is how it is directly implemented in GHC)
as functions similar to 

data World   -- no constructors, World is an abstract type 
             -- representing the 'state of the universe'
type IO a = World -> (a,World)

meaning an IO action that returns a Char is actually a pure function from the
World to a new World and the Char. 

now, imagine we didn't have global variables, then we would have to pass
the values of the global variables everywhere, collecting the new
variables from the function results. note that this is exactly what the
IO monad does! So, all the global variables semantics are completly
defined by 'adding' the values of the global variables to World.   

if World were actually directly implemented, it might look something

data World = World {
        keyPressedOnStandardInput :: Maybe Char,
        theFilesystem :: [(FileName,Contents)],
        presidentOfTheUnitedStates :: String,
        currentMoodOfUser :: Mood,
        -- every other property of the universe

(you can see why we like to keep World abstract :))

a global variable is just another entry in the World record. 

This is why global variables are safe to use in a lazy functional
language (perhaps against intuition), their use is confined to the IO
monad, which passes around the state of everything (including the global
variables) in a purely functional way. The problem is there is just no
mechanism in haskell to declare them and it is unclear what said
mechanism should look like which is what the whole debate is
about :)   


> 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.

Oh yes. no one is wanting that.  


John Meacham - ⑆repetae.net⑆john⑈ 

More information about the Haskell-Cafe mailing list