ekmett / exceptions

mtl friendly exceptions
Other
49 stars 32 forks source link

Add a traslating transformer to implement `MonadThrow` in terms of `MonadIO` #89

Open ocharles opened 2 years ago

ocharles commented 2 years ago

I have the following:

foo :: (MonadWhatever m, MonadThrow m) => ... -> m ()

Later, I have

bar :: (MonadIO, MonadWhatever m) =>
bar = do
  ...
  foo
  ...

However, this won't typecheck because bar lacks the MonadThrow constraint necessary for foo. I don't want to add a MonadThrow constraint because I know that MonadIO implements that. My suggestion is that exceptions gains a new transformer that translates MonadThrow into MonadIO:

-- | Translate 'MonadThrow' constraints to an underlying 'MonadIO' instance.
newtype ThrowToIOT m a = ThrowToIOT { throwToIO :: m a }
  deriving newtype (Functor, Applicative, Monad, MonadIO, MonadUnliftIO)

instance MonadTrans ThrowToIOT where
  lift = ThrowToIOT

instance MonadIO m => MonadThrow (ThrowToIOT m) where
  throwM = liftIO . throwM

With this, I can now write:

bar :: (MonadIO, MonadWhatever m) =>
bar = do
  ...
  throwToIO foo
  ...

and everyone is happy.