[Haskell-cafe] Re: Yet another IO initializer: Effectful declarations and an ACIO monad

George Russell ger at informatik.uni-bremen.de
Fri Nov 26 07:08:10 EST 2004

Ian.Stark at ed.ac.uk wrote:
(initialising by wish)
> This indeed can't be proved central+affine, because it isn't.  So instead,
> choose one of the following:

 > 1 (Good) Indirection:

 >   declare gc <- newIORef None; so that gc is a global variable holding a
 >  (Maybe GraphicsContext).  Initialise the contents in your main IO
 >  action; and then pull out the value any time you need to look at it.
 >  Yes, you need to explicitly initialise it; but you don't need then to
 >  pass the initialized handle all around your code.  The painful plumbing
 >  goes away.
I think this is either unwieldy or inefficient. Imagine a large library
containing lots of these things which need to be initialised if used.  Then
I predict that one of two things will happen
(a) people will end up writing boilerplace code at the start of the main
     action which does
        ... blah blah ...
(b) (more likely).  There will be a single initialisation function for the
     library, which initialises everything, even the stuff you don't actually

> 2 (Neutral) As above, but write getGC :: IO GraphicsContext that looks in
>   gc, and if there is None then calls out to wish, or whatever, to
>   initialise it first.
>   Sound, but getGC then hides some wildly varying behaviour.
I think this is basically what my Data.GlobalVariables module does,
except that most of the work is done for you and you also get the
bonus of being able to create fresh worlds within your program (so
that two copies of main can be run concurrently, for example).

> 3 (Evil) Give in to the dark side.  Have unsafeIOtoACIO, write a
>   declaration using it, and hope that your compiler does the easy thing
>   and executes all declarations at the start of the program.
>   In fact not much worse than (2); only now the possible effect points
>   have leapt from all uses of gc to all uses of IO.

The real danger of unsafeIOtoACIO is that a compiler may well choose
to implement ACIO declarations by only initialising variables when
they are actually needed.  Thus possible effect points will not just
be all uses of IO, but everywhere in the program.
> But they don't open them, right?  The whole point of stdin/stdout/stderr
> being fixed integers is that these handles are already opened when the
> program starts.

Surely not?  Haskell buffers have to be initialised and so on.

> Yes, the system StdGen really does have to get initialised.  But the
> presumed readRandomNumberFromSystem() is ACIO if it's random (OK, so if
> it's implemented by opening /dev/random, then this would have to be
> wrapped in assertIOisACIO).

So assertIOisACIO will have to exist, if only in an internal GHC module ...

More information about the Haskell-Cafe mailing list