[Haskell] threading mutable state through callbacks

Adrian Hey ahey at iee.org
Tue Oct 12 15:25:31 EDT 2004

On Tuesday 12 Oct 2004 6:28 pm, Jules Bean wrote:
> On 12 Oct 2004, at 14:08, Adrian Hey wrote:
> >> x <- someAction
> >> y <- someAction(x)
> >
> > I would say keep things as they currently are with the unsafePerformIO
> > solution, I.E. Order unspecified, the action that creates a particular
> > top level thing is executed only once, when the value of thing is
> > demanded (perhaps not at all).
> Also consider the case of
> z = someAction(y)
> Here z is a value outside the IO monad, calculated using a function
> outside the IO monad, based on a value (y) which also lies outside the
> IO monad... What sane semantics will explain when the actions which led
> to the value y should be taken?

I've never really understood what people mean by things being "inside" and
"outside" the IO monad :-(

Assuming from Vincenzos original example that ..

someAction :: SomeType -> IO Thing

then in your example..

z :: IO Thing

So z is a perfectly ordinary value. The someAction that creates y will
be executed only once, as soon as the value of y is needed, which
(assuming someAction is strict) will be as soon as the value of z
is needed, I.E. "Whenever"

The only real insanity with the current situation is the loss of
referential transparency implied by the use of unsafePerformIO, which
is why various pragma hacks and compiler switches need to be used (in
order to prevent inappropriate substitutions). What I want to do
is to make this or something similar "official", so the compiler really
knows not to do this inappropriate subsitution in any event, even if
the programmer forgot to use the necessary pragmas or compiler flags,
or just didn't understand why they are needed.

This still leaves the uncertainty of exactly when the creation occurs,
but this is a minor issue IMO. We have the same problem with finalisers
and any concurrent code. Either it just doesn't matter, or if it does
then it's the programmers responsibility to use existing mechanisms
(such as seq) to control things.

> I think what people are trying to suggest is an 'initialization phase'
> in the IO monad, which takes place "before" the pure functions are
> defined. At compile time, conceptually. I don't have any clear idea how
> that should be made precise.

I can't speak for what others are trying to suggest, but that isn't
what I have in mind.

What I want is non-hack mechanism for creation of arbitrarily complex
"things with identity" at the top level. I guess you could arrange that
all such things were constructed at run time before executing main, but
I don't see any real advantage in that.

Adrian Hey

More information about the Haskell mailing list