[Haskell-cafe] Re: Yet another IO initializer: Effectful
declarations and an ACIO monad
Ian.Stark at ed.ac.uk
Ian.Stark at ed.ac.uk
Fri Nov 26 06:28:54 EST 2004
On Fri, 26 Nov 2004, George Russell wrote:
> Ian Stark wrote (snipped):
> > Way back in this thread, Koen Claessen mentioned the idea of a commutative
> > version of the IO monad for handling things with identity. That doesn't quite
> > do it, but I have a refinement that might. The thing is to focus on IO
> > computations that are:
> > a) central -- their effect commutes with every other IO action
> > b) affine -- their effect is not directly observable, and can be discarded.
> Unfortunately I have a number of examples where I use global variables with
> initialisation actions which cannot conceivably be proven to be central & affine
> by the compiler. For example, where I want to call up an external program (such
> as wish) which I will later use for doing graphics.
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
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.
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 Haskell libraries would run into a similar problem when they tried to
> open stdin/stdout/stderr.
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
> Or indeed when they tried to implement RandomGen, which I presume is
> going to want to get at the system clock to seed the random number
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).
Ian Stark http://www.ed.ac.uk/~stark
LFCS, School of Informatics, The University of Edinburgh, Scotland
More information about the Haskell-Cafe