Monad
the class represents all things which are monads---it's an adjective more than a noun. If you'd like to convert a particular monad into a value which is generic in all monads that type would look like one of these
Monad m => IO a -> m a
Monad m => Maybe a -> m a
Monad m => [a] -> m a
Monad m => Either e a -> m a
and it's in general impossible, though one type of very special monads has this property.
Another thing you might do is use a Monad
transformer which IO
at the bottom. This means that you layer another monad "on top of" IO
. This lets you have the general operation
lift :: MonadTrans t => m a -> t m a -- notice that t takes two parameters
lift :: IO a -> MyTransformer IO a -- specializing the generic function
and, depending on what MyTransformer
is, the specific operation
runMyTransformer :: MyTransformer m a -> m a
runMyTransformer :: MyTransformer IO a -> IO a -- specialized
For instance, the very simplest MonadTrans
is IdT
.
newtype IdT m a = IdT { runIdT :: m a } deriving Functor
instance Monad m => Monad (IdT m) where
return a = IdT (return a)
IdT ma >>= f = IdT (ma >>= runIdT . f)
instance MonadTrans IdT where
lift ma = IdT ma
Giving us the operations
lift :: IO a -> IdT IO a
runIdT :: IdT IO a -> IO a
which are just inverses of one another, in this case. In general the behavior can be much more complex.