{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE QuantifiedConstraints #-}
#endif
module Control.Monad.Trans.Compose (
ComposeT(ComposeT, getComposeT),
mapComposeT
) where
import Control.Applicative (
Applicative(pure, (<*>), (*>), (<*)), Alternative(empty, (<|>)) )
import Control.Monad (MonadPlus(mzero, mplus), liftM)
import Control.Monad.Cont.Class (MonadCont(callCC))
import Control.Monad.Error.Class (MonadError(throwError, catchError))
import Control.Monad.Morph (MFunctor(hoist))
import Control.Monad.RWS.Class (MonadRWS)
import Control.Monad.Reader.Class (MonadReader(ask, local, reader))
import Control.Monad.State.Class (MonadState(get, put, state))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Monad.Writer.Class (MonadWriter(writer, tell, listen, pass))
import Control.Monad.IO.Class (MonadIO(liftIO))
import Data.Foldable (Foldable(fold, foldMap, foldr, foldl, foldr1, foldl1))
import Data.Traversable (Traversable(traverse, sequenceA, mapM, sequence))
import Prelude hiding (foldr, foldl, foldr1, foldl1, mapM, sequence)
#if __GLASGOW_HASKELL__ >= 800
import Control.Monad.Fail (MonadFail(..))
import qualified Control.Monad.Fail
#endif
infixr 9 `ComposeT`
newtype ComposeT (f :: (* -> *) -> * -> *) (g :: (* -> *) -> * -> *) m a
= ComposeT { getComposeT :: f (g m) a }
deriving (Eq, Ord, Read, Show)
instance (MFunctor f, MonadTrans f, MonadTrans g) => MonadTrans (ComposeT f g)
where
lift = ComposeT . hoist lift . lift
#if __GLASGOW_HASKELL__ >= 806
instance (MFunctor f, MFunctor g, forall m. Monad m => Monad (g m))
=> MFunctor (ComposeT f g) where
hoist f (ComposeT m) = ComposeT (hoist (hoist f) m)
#endif
instance Functor (f (g m)) => Functor (ComposeT f g m) where
fmap f (ComposeT m) = ComposeT (fmap f m)
instance Applicative (f (g m)) => Applicative (ComposeT f g m) where
pure a = ComposeT (pure a)
ComposeT f <*> ComposeT a = ComposeT (f <*> a)
ComposeT a *> ComposeT b = ComposeT (a *> b)
ComposeT a <* ComposeT b = ComposeT (a <* b)
instance Alternative (f (g m)) => Alternative (ComposeT f g m) where
empty = ComposeT empty
ComposeT a <|> ComposeT b = ComposeT (a <|> b)
instance Monad (f (g m)) => Monad (ComposeT f g m) where
return a = ComposeT (return a)
m >>= f = ComposeT (getComposeT m >>= \x -> getComposeT (f x))
#if __GLASGOW_HASKELL__ < 808
fail e = ComposeT (Prelude.fail e)
#endif
#if __GLASGOW_HASKELL__ >= 800
instance MonadFail (f (g m)) => MonadFail (ComposeT f g m) where
fail e = ComposeT (Control.Monad.Fail.fail e)
#endif
instance MonadPlus (f (g m)) => MonadPlus (ComposeT f g m) where
mzero = ComposeT mzero
ComposeT a `mplus` ComposeT b = ComposeT (a `mplus` b)
instance MonadIO (f (g m)) => MonadIO (ComposeT f g m) where
liftIO m = ComposeT (liftIO m)
instance Foldable (f (g m)) => Foldable (ComposeT f g m) where
fold (ComposeT m) = fold m
foldMap f (ComposeT m) = foldMap f m
foldr f a (ComposeT m) = foldr f a m
foldl f a (ComposeT m) = foldl f a m
foldr1 f (ComposeT m) = foldr1 f m
foldl1 f (ComposeT m) = foldl1 f m
instance Traversable (f (g m)) => Traversable (ComposeT f g m) where
traverse f (ComposeT m) = fmap ComposeT (traverse f m)
sequenceA (ComposeT m) = fmap ComposeT (sequenceA m)
mapM f (ComposeT m) = liftM ComposeT (mapM f m)
sequence (ComposeT m) = liftM ComposeT (sequence m)
instance MonadCont (f (g m)) => MonadCont (ComposeT f g m) where
callCC f = ComposeT $ callCC $ \c -> getComposeT (f (ComposeT . c))
instance MonadError e (f (g m)) => MonadError e (ComposeT f g m) where
throwError = ComposeT . throwError
catchError m h = ComposeT $ catchError (getComposeT m) (getComposeT . h)
instance MonadRWS r w s (f (g m)) => MonadRWS r w s (ComposeT f g m)
instance MonadReader r (f (g m)) => MonadReader r (ComposeT f g m) where
ask = ComposeT ask
local = mapComposeT . local
reader = ComposeT . reader
instance MonadState s (f (g m)) => MonadState s (ComposeT f g m) where
get = ComposeT get
put = ComposeT . put
state = ComposeT . state
instance MonadWriter w (f (g m)) => MonadWriter w (ComposeT f g m) where
writer = ComposeT . writer
tell = ComposeT . tell
listen = mapComposeT listen
pass = mapComposeT pass
mapComposeT :: (f (g m) a -> p (q n) b) -> ComposeT f g m a -> ComposeT p q n b
mapComposeT f = ComposeT . f . getComposeT