Generalize MonadIO to MonadBase
Bas van Dijk
v.dijk.bas at gmail.com
Mon Apr 19 19:50:55 EDT 2010
Hello,
(This should actually be a reply to the "Move MonadIO to base"
thread[1] but I didn't want to break up the extremely interesting
discussion on the MonadTransMorph class)
Would it be useful if we got rid of MonadIO:
class (Monad m) => MonadIO m where liftIO :: IO a -> m a
and replace it with the generalization:
class (Monad m, Monad n) => MonadBase m n | m -> n where inBase :: n a -> m a
which would allow lifting not just IO but any base monad into a stack
of monad transformers.
It could be implemented as follows:
--------------------------------------------------------------------------------------
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
module MonadBase where
import Data.Monoid ( Monoid )
import Control.Monad.ST ( ST )
import Control.Monad.Trans.Class ( MonadTrans, lift )
import Control.Monad.Trans.Cont ( ContT )
import Control.Monad.Trans.Error ( ErrorT, Error )
import Control.Monad.Trans.Identity ( IdentityT )
import Control.Monad.Trans.List ( ListT )
import Control.Monad.Trans.Maybe ( MaybeT )
import Control.Monad.Trans.RWS ( RWST )
import Control.Monad.Trans.Reader ( ReaderT )
import Control.Monad.Trans.State ( StateT )
import Control.Monad.Trans.Writer ( WriterT )
class (Monad m, Monad n) => MonadBase m n | m -> n where
inBase :: n a -> m a
instance MonadBase IO IO where inBase = id
instance MonadBase Maybe Maybe where inBase = id
instance MonadBase [] [] where inBase = id
instance MonadBase (ST s) (ST s) where inBase = id
-- etc.
-- This would be nice but will cause lots of trouble:
-- instance Monad m => MonadBase m m where inBase = id
liftInBase :: (MonadTrans t, MonadBase m n) => n a -> t m a
liftInBase = lift . inBase
instance (MonadBase m n) => MonadBase (ContT r m) n
where inBase = liftInBase
instance (MonadBase m n) => MonadBase (IdentityT m) n
where inBase = liftInBase
instance (MonadBase m n) => MonadBase (ListT m) n
where inBase = liftInBase
instance (MonadBase m n) => MonadBase (MaybeT m) n
where inBase = liftInBase
instance (MonadBase m n) => MonadBase (ReaderT r m) n
where inBase = liftInBase
instance (MonadBase m n) => MonadBase (StateT s m) n
where inBase = liftInBase
instance (MonadBase m n, Error e) => MonadBase (ErrorT e m) n
where inBase = liftInBase
instance (MonadBase m n, Monoid w) => MonadBase (RWST r w s m) n
where inBase = liftInBase
instance (MonadBase m n, Monoid w) => MonadBase (WriterT w m) n
where inBase = liftInBase
{-# DEPRECATED liftIO "Use inBase instead." #-}
liftIO :: MonadBase m IO => IO a -> m a
liftIO = inBase
--------------------------------------------------------------------------------------
I noticed that MonadLib also provides this class[2].
regards
Bas
[1] http://thread.gmane.org/gmane.comp.lang.haskell.libraries/12877
[2] http://hackage.haskell.org/packages/archive/monadLib/3.6.1/doc/html/MonadLib.html#t%3ABaseM
More information about the Libraries
mailing list