[Haskell] Re: threading mutable state through callbacks
oleg at pobox.com
oleg at pobox.com
Thu Oct 7 21:44:26 EDT 2004
Jules Bean wrote:
> Unfortunately, it's not going to work. It's not going to work because
> some of the procedures take callbacks, and the callbacks are values of
> type IO (). I can see two solutions to this:
>
> a) revert to using an IORef, and use lexical scoping to define my
> callbacks in a location such that the reference to the environment is
> in scope. This will work, but it's just not convenient to define all
> your functions inside another function so you can do a lexical scoping
> trick...
>
> b) write the callbacks as values of type
>
> StateT Env IO ()
>
> Is this the right approach? Is there a better one?
Yes: implicit parameters and implicit configurations. The end user code
is often identical in both of these approaches (but the latter may
require a bit more preparation. OTH, implicit parameters are supported
by the compiler whereas the latter is just a Haskell library). Both
approaches are compared in Appendix A of the paper
http://www.eecs.harvard.edu/~ccshan/prepose/prepose.pdf
The example is writing JNI functions in Haskell. Incidentally, the
example illustrates passing of the implicit state (JNIEnv pointer)
_around_ the exception handler. The problem is that the function
'handle' has the type
handle :: (Exception -> IO a) -> IO a -> IO a
rather than
handle :: (Exception -> MonadIO a) -> MonadIO a -> MonadIO a
> revert to using an IORef, and use lexical scoping to define my
> callbacks in a location such that the reference to the environment is
> in scope. This will work, but it's just not convenient to define all
> your functions inside another function so you can do a lexical scoping
> trick...
The stated motivation of the implicit configurations is precisely
that: make it appear that the IORef is `lexically scoped' over all of its
clients without putting all the clients inside one giant function.
The master file for the paper
http://www.eecs.harvard.edu/~ccshan/prepose/prepose.lhs
is a literate Haskell code, which you can load into GHCi as it is. You
can then run all of the examples in the paper.
If you have trouble using implicit configurations, have a particular
application in mind and can turn it into a self-contained example (by
replacing various functions with stubs wherever possible: e.g., see
the very end of prepose.lhs), you may want to let Ken and me
know. I'll see what can be done.
More information about the Haskell
mailing list