Skip to content

Fix Alternative instance for IO

The Alternative instance for IO is currently defined in GHC.Base, using

(<|>) = mplusIO

Hunting further, mplusIO is defined in GHC.IO as

mplusIO :: IO a -> IO a -> IO a
mplusIO m n = m `catchException` \ (_ :: IOError) -> n

Why this is (possibly) wrong

Quoting documentation in Control.Exception

Applying mask to an exception handler

There's an implied mask around every exception handler in a call to one of the catch family of functions. This is because that is what you want most of the time - it eliminates a common race condition in starting an exception handler, because there may be no exception handler on the stack to handle another exception if one arrives immediately. If asynchronous exceptions are masked on entering the handler, though, we have time to install a new exception handler before being interrupted. If this weren't the default, one would have to write something like

 mask $ \restore ->
      catch (restore (...))
            (\e -> handler)

If you need to unmask asynchronous exceptions again in the exception handler, restore can be used there too.

Note that try and friends do not have a similar default, because there is no exception handler in this case. Don't use try for recovering from an asynchronous exception.

Being that mplusIO only catches exceptions of type IOError, it is not suited for cleanup work. It is more likely useful for running a fallback action should the first one fail. In this case, one would not want to prevent asynchronous exceptions from being able to interrupt the application in the alternative branch.

So I would suggest a better implementation for mplusIO should be based on try rather than catch

Something like:

mplusIO :: IO a -> IO a -> IO a
mplusIO m n = do
  res <- catchException (m >>= \ v -> return (Right v)) (\e -> return (Left e))
  case res of
    Right a -> return a
    Left (e :: IOError) -> n
Edited by Isaac Berger
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information