[Haskell] threading mutable state through callbacks

John Meacham john at repetae.net
Wed Oct 13 20:43:32 EDT 2004


On Wed, Oct 13, 2004 at 03:34:07PM +0100, Simon Marlow wrote:
> On 13 October 2004 03:36, Wolfgang Thaller wrote:
> 
> > b) Some predetermined order, with semantics like mdo:
> > 
> > John Meacham wrote:
> > 
> >> The basic idea is that your entire program behaves as if in a giant
> >> 'mdo' block, ordered in module dependency order.
> 
> I also like the mdo idea - in fact it occurred to me yesterday, but I
> wasn't sure whether there would be any gotchas when the details were
> worked out, and it looks like John has established that things work out
> nicely.
> 
> GHC already has an initialisation procedure for each module in the
> program which could be adapted to run the initialisation-time IO
> actions, with a little effort.
> 
> I'm more worried about what other changes we have to make to the
> compiler: if we can avoid having to flag top-level bindings as
> monadic/non-monadic all the way through the compiler, then we could
> avoid a pervasive change to the compiler.  At the moment I can't see an
> obvious way to do that.

I was thinking that all that would need to be done is a rewriting of

fooVar <- newIORef 42
barVar <- newIORef 3

to


fooVar = error "Loop detecting in binding of fooVar"
barVar = error "Loop detecting in binding of barVar"


_init_ = do
        ...
        x <- newIORef 42 
        veryUnsafeUpdate# fooVar x
        y <- newIORef 3
        veryUnsafeUpdate# barVar y
        ...

where
veryUnsafeUpdate# :: a -> a -> IO ()
replaces its first argument with an indirection to its second argument.
(this is very unsafe, so probably shouldn't be exposed, but should be
easy enough inside the compiler)

other than than one call to veryUnsafeUpdate#, global bindings can be
treated exactly like CAFs. 

The only tricky things are we need to typecheck before carying out this
translation (to get the right monomorphic types for fooVar and barVar)
and ensure they remain CAFs (which a NOINLINE note should acomplish, but
even might not be needed if we include the _init_ routine in the
optimization as then the routines will be called from more than one
place).

we no longer need to worry about the CSE problem either if we make sure
the error messages are distinct (which they will be if we include the
file/line number) 

== Another idea ==

A useful addition to ghc would be an ability to register exit handlers
which are run after main exits. then this gives us a nice general
initialization/finalization framework for modules for free.. like

_ <- do
        global initialization

_ <- onExit $ do
        global finalization


== Another thought ==

We should come up with some consistent terminology for this extension, I
keep on having to think about it and sometimes change mid-paragraph :) I
was thinking

if
a = let 
    b = ... 
   in ...

c <- do
    d <- ...
    ...

then 
a - global declaration
b - local declaration
c - global binding
d - local binding

for consistency, perhaps something bound by a lambda should be called a
lambda binding. 


does this terminology make sense? perhaps there is another more obivous
one? any suggestions?



        John


-- 
John Meacham - ⑆repetae.net⑆john⑈ 


More information about the Haskell mailing list