[Haskell-cafe] Re: Asynchronous exception wormholes kill modularity

Bas van Dijk v.dijk.bas at gmail.com
Thu Apr 22 05:08:33 EDT 2010


On Thu, Apr 22, 2010 at 10:30 AM, Simon Marlow <marlowsd at gmail.com> wrote:
> Funnily enough, before posting the above message I followed exactly the line
> of reasoning you detail below to discover that there isn't a way to fix this
> using parametricity.  It's useful to have it documented, though - thanks.

In their paper on "Lightweight Monadic Regions" [1] Oleg Kiseljov and
Chung-chieh Shan had to solve a very similar problem.

To quote the middle of section 4.3:

"...Instead of leaking a handle, we may try to leak a computation
involving the handle:

do ac <- newRgn (do
  h2 <- newSHandle "fname2" ReadMode
  return (shGetLine h2))
ac

This code is unsafe because newRgn closes the handle h2 when
the child computation exits. Executing the action ac outside of
newRgn would attempt to read from an already closed handle.
Fortunately, this code raises a type error. The handle h2 has the
type SHandle (IORT s m), where s is quantified in the type of
newRgn. The computation shGetLine h2 therefore has the type

(MonadRaise (IORT s m) m2, RMonadIO m2) => m2 String

Since do-bindings are monomorphic, the type checker must resolve
the two constraints above to infer a type for ac. Since m2
is unknown, constraint resolution fails and yields a type error. Indeed,
every way to instantiate m2 that satisfies the suffix constraint
MonadRaise (IORT s m) m2 mentions s, but the type of ac,
which contains m2, cannot mention s because ac takes scope beyond
s. It does not help to existentially quantify over s in the type
of ac, because the type error would just shift to where ac is used..."

If we look at:

unmaskHack3 :: IO a -> IO a
unmaskHack3 m = do
 mv <- newEmptyMVar
 tid <- forkIOWithUnmask $ \unmask -> putMVar mv (apply unmask m)
 unmaskedM <- takeMVar mv
 unmaskedM -- (or use join)

the correspondence is clear:

newRgn    = forkIOWithUnnmask
h2        = unmask
shGetLine = apply
ac        = unmaskedM

I'm hoping we can solve this in a similar way!

regards

Bas

[1] http://okmij.org/ftp/Haskell/regions.html#light-weight


More information about the Haskell-Cafe mailing list