[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
goes away.
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
program starts.
> 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
> generator.
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
mailing list