[Haskell-cafe] ACIO versus Execution Contexts

Adrian Hey ahey at iee.org
Tue Nov 30 05:41:10 EST 2004

Hello George,

I've been looking at your global variables library. As far as I can tell
it seems to be aimed at solving a rather different problem from that the
top-level <- bindings are aimed at. So I don't think you can really
compare them. One is not a substitute for the other.

In particular, the purpose of top level <- bindings IMO is *not* to
provide "global variables" (though they could be abused this way).
If you consider the example..

 userInit <- oneShot realInit

..the top level MVar created is not global. It doesn't even scope over
an entire module, it's buried in a closure. This kind of use would be
pretty typical I think. Even when you do have top level IORefs (or
more complex mutable data structures) scoping over an entire module,
generally they won't be exported by that module. Instead access is
strictly limited to a few carefully defined IO actions, and these
are exported.

Also, we don't want different threads to have their own versions of
these. They are for use in situations where you need to represent
state associated with a genuinely unique resource (eg top level
stateful C library or hardware IO device).

So in such situations it's both unnecessary and downright dangerous
to provide a "newResourceState" constructor and pass this to releted
IO routines as a parameter. But in the absence of such a constructor, how
can the state exist at all, unless one allows top level <- bindings?
This is the problem I think we're trying to solve with the top level <-

On Monday 29 Nov 2004 1:19 pm, George Russell wrote:
> Questions
> ---------
> 1.  Is there anything people would like to do with ACIO for which execution
> contexts would not be practical?

Yes, see above. Big problems with "execution contexts" (at least as currently
proposed) IMO are..
1- Use of multiple dictionaries breaks the uniqueness property of top level
   <- bindings.
2- Constraint of one dictionary entry per type is particularly severe I think,
   especially as it's not statically checkable.
3- Variables are anonymous and can only be "got at" via IO monad. With top
   level <- bindings, the bound variables are perfectly ordinary top level
   Haskell identifiers which can appear in other top level definitions.
4- Even an optimisted implementation will probably be very much slower
   than top level <- bindings.

> 2.  Which if either of the proposals would the gods responsible for
> implementing Haskell compilers favour?

Dunno. But if it makes life any easier, I would be quite happy to forget
about special restricted monads and just use IO instead. The resulting
programs would still be sound I think, but it makes it the programmers
responsibility not to do anything stupid in a top level <- binding.

It seems to me two properties are highly desirable..

1 - Observable behaviour should not depend on ordering of <- bindings
    in a module
2 - Observable behavior should not depend on ordering of imports in
    main or any other module. 

AFAICS all that's needed to ensure this is that top level <- bindings
are reduced lazily (as with the unsafePerformIO hack).

I know that's not ideal, but it's a heck of a lot better than using
unsafePerformIO. We have a similar situation with finalisers at the
moment. The restricted monads guarantee a third property..

3 - Observable behaviour does not depend on reduction order of top
    level <- bindings *in any way*. They could be reduced at compile
    time say (at least with SafeIO, not sure about ACIO).

This would be nice to enforce via the type system, but I could live
without it.

Adrian Hey

More information about the Haskell-Cafe mailing list