I'm actually not sure whether this is an issue, or if it fits the project goals at all, but I keep wondering why we can't have an encapsulation of core exceptions from IO actions (since they are far too common) under a more type-safe approach such as MonadError e m.
What I'm thinking about is something like
import Control.Monad.Except
import Control.Exception (Exception (..), try)
liftErrorIO :: (Exception e, MonadIO m, MonadError e m) => IO a -> m a
liftErrorIO = liftIO . try >=> either throwError return
liftedBracket :: (Exception e, MonadIO m, MonadError e m) =>
m a
-> (a -> m b)
-> (a -> m c)
-> m c
liftedBracket acquire release comp = do
resource <- acquire
result <- catchError (comp resource) (\e -> release resource >> throwError e)
_ <- release resource
return result
I'm actually not sure whether this is an issue, or if it fits the project goals at all, but I keep wondering why we can't have an encapsulation of core exceptions from
IO
actions (since they are far too common) under a more type-safe approach such asMonadError e m
.What I'm thinking about is something like