base: Add `Control.Exception.throwIOLeft` utility
The main motivation for this utility is to simplify working with
actions of type IO (Either e a)
An alternative approach could have been to directly implement a utility of type:
??? :: IO (Either e a) -> IO a
… but I went with the current type for two reasons:
-
I conducted a poll to see which version people preferred:
https://twitter.com/GabriellaG439/status/1428589302951268355
-
The current version also has nicer theoretical properties, like being a monad morphism
There's another property I didn't mention in the documentation, which is that
throwLeft
distributes over exception handling, too:throwIOLeft (m `catchError` \x -> f x) = throwIOLeft m `catchError` \x -> throwIOLeft (f x) throwIOLeft (throwError e) = throwError e
-
It's fairly ergonomic to implement the latter type in terms of the current type
The latter type is just
(>>= throwIOLeft)