Given an arbitrary monad, is there a way to create a monad transformer based on that monad? I googled this question and didn't see anywhere where it was addressed (although I may have missed it) so I just tried to do it myself, and I got close, I think:
import Control.Monad.Trans.Class (MonadTrans, lift)
newtype ToMonadTrans m2 m1 a = ToMonadTrans (m2 (m1 a))
instance (Functor m2, Functor m1) => Functor (ToMonadTrans m2 m1) where
fmap f (ToMonadTrans x) = ToMonadTrans (fmap (fmap f) x)
instance (Applicative m2, Applicative m1) => Applicative (ToMonadTrans m2 m1) where
pure = ToMonadTrans . pure . pure
ToMonadTrans f <*> ToMonadTrans x = ToMonadTrans (((<*>) . (fmap (<*>))) f x)
instance (Monad m2, Monad m1) => Monad (ToMonadTrans m2 m1) where
ToMonadTrans x >>= ToMonadTrans f = ToMonadTrans (???)
instance Monad m2 => MonadTrans (ToMonadTrans m2) where
lift x = ToMonadTrans (pure x)
The idea here is that ToMonadTrans Maybe
is the same as MaybeT
. The good thing about this approach (if it works) is that you can make any monad into a MonadTrans
, allowing one to layer any monad without having to write a corresponding specialised transformer.
As you can see, I implemented MonadTrans
as well as Functor
and Applicative
, the only place I got stuck is Monad
.
My questions are:
- Can this be done?
- Has this been done in a package on hackage?