On 04/08/10 04:23, Simon Marlow wrote:
On 07/04/2010 18:54, Isaac Dupree wrote:
On 04/07/10 11:12, Simon Marlow wrote:
It's possible to mis-use the API, e.g.

getUnmask = mask return

...incidentally,
unmask a = mask (\restore -> return restore) >>= (\restore -> restore a)

That doesn't work, as in it can't be used to unmask exceptions when they
are masked. The 'restore' you get just restores the state to its
current, i.e. masked, state.

oh good point. Then you're right, anyone who was trying to work around it would be doing something obviously wrong.

mask :: ((IO a -> IO a) -> IO b) -> IO b

It needs to be :: ((forall a. IO a -> IO a) -> IO b) -> IO b
so that you can use 'restore' on two different pieces of IO if you need
to. (alas, this requires not just Rank2Types but RankNTypes. Also, it
doesn't cure the loophole. But I think it's still essential.)

Sigh, yes I suppose that's true, but I've never encountered a case where
I needed to call unmask more than once, let alone at different types,
within the scope of a mask. Anyone else?

FWIW, the function I made up to test my theory was as below; I haven't thought of any "actual" uses yet:

finally2 :: IO a1 -> IO a2 -> IO b -> IO (a1, a2)
finally2 a1 a2 b =
  mask $ \restore -> do
    r <- (liftM2 (,) (restore a1) (restore a2)) `onException` b
    b
    return r

-Isaac
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to