
Simon Marlow wrote:
I came to the conclusion that counting nesting layers doesn't solve the problem: the wormhole still exists in the form of nested unmasks. That is, a library function could always escape out of a masked context by writing
unmask $ unmask $ unmask $ ...
enough times. [...] mask :: ((IO a -> IO a) -> IO b) -> IO b mask io = do b <- blocked if b then io id else block $ io unblock
to be used like this:
a `finally` b = mask $ \restore -> do r <- restore a `onException` b b return r
So the property we want is that if I call a library function
mask $ \_ -> call_library_function
then there's no way that the library function can unmask exceptions. If all they have access to is 'mask', then that's true. [...] It's possible to mis-use the API, e.g.
getUnmask = mask return
Given that both the "simple" mask/unmask and your alternate proposal have backdoors, is the extra complexity really worth it? The problem with the existing API is that it's not possible even for well-behaved library code to use block/unblock without screwing up callers. With the simple mask/unmask, the rule is simply that you don't call unmask except within the context of your own mask calls. Ganesh =============================================================================== Please access the attached hyperlink for an important electronic communications disclaimer: http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html ===============================================================================