About a year ago, I wrote a proposal for IOE, enabling checked exceptions in IO. It got fairly negative reactions, which is fine. This is a smaller change that I think might be less controversial than that.
Currently, we have IO
that represents both impurity and the ability to throw exceptions. Here, I’m only talking about exceptions in the Haskell runtime; OOM and other catastrophic errors can also happen in pure code, so I’m not worried about those. What if we had some new type e.g. UIO
that only represented impurity, and cannot throw any exceptions? That way, if you have a UIO
, you don’t need to worry about catching exceptions.
One example motivation for this is ExceptT; ExceptT is notorious for being leaky. You might think ExceptT FooError IO ()
can only throw FooError, but any other error could be thrown in IO. ExceptT FooError UIO ()
would not have this problem. You can imagine other similar situations, where maybe you have a subsystem in IO, but you want the guarantee that it only throws FooError, so you want to make sure that any other IO function you call is UIO, so you don’t accidentally propagate some other exception.
Existing code like IORef could be UIO today, since none of those functions can throw exceptions. C FFI functions can also all be UIO, since C code can’t throw Haskell exceptions.
Thoughts? Is this sufficiently motivated? Is it sufficiently useful?