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
...
I have the following:
Later, I have
However, this won't typecheck because
bar
lacks theMonadThrow
constraint necessary forfoo
. I don't want to add aMonadThrow
constraint because I know thatMonadIO
implements that. My suggestion is thatexceptions
gains a new transformer that translatesMonadThrow
intoMonadIO
:With this, I can now write:
and everyone is happy.