module Control.Monad.Trans.MultiWriter.Strict
(
MultiWriterT(..)
, MultiWriterTNull
, MultiWriter
, MonadMultiWriter(..)
, runMultiWriterT
, runMultiWriterTAW
, runMultiWriterTWA
, runMultiWriterTW
, runMultiWriterTNil
, runMultiWriterTNil_
, withMultiWriter
, withMultiWriterAW
, withMultiWriterWA
, withMultiWriterW
, withMultiWriters
, withMultiWritersAW
, withMultiWritersWA
, withMultiWritersW
, inflateWriter
, mapMultiWriterT
, mGetRaw
, mPutRaw
)
where
import Data.HList.HList
import Data.HList.ContainsType
import Control.Monad.Trans.MultiWriter.Class ( MonadMultiWriter(..) )
import Control.Monad.State.Strict ( StateT(..)
, MonadState(..)
, execStateT
, evalStateT
, mapStateT )
import Control.Monad.Writer.Strict ( WriterT(..) )
import Control.Monad.Trans.Class ( MonadTrans
, lift )
import Control.Monad.Writer.Class ( MonadWriter
, listen
, tell
, writer
, pass )
import Data.Functor.Identity ( Identity )
import Control.Applicative ( Applicative(..)
, Alternative(..)
)
import Control.Monad ( MonadPlus(..)
, liftM
, ap
, void )
import Control.Monad.Base ( MonadBase(..)
, liftBaseDefault
)
import Control.Monad.Trans.Control ( MonadTransControl(..)
, MonadBaseControl(..)
, ComposeSt
, defaultLiftBaseWith
, defaultRestoreM
)
import Control.Monad.Fix ( MonadFix(..) )
import Control.Monad.IO.Class ( MonadIO(..) )
import Data.Monoid
newtype MultiWriterT x m a = MultiWriterT {
runMultiWriterTRaw :: StateT (HList x) m a
}
type MultiWriterTNull = MultiWriterT '[]
type MultiWriter x a = MultiWriterT x Identity a
instance (Functor f) => Functor (MultiWriterT x f) where
fmap f = MultiWriterT . fmap f . runMultiWriterTRaw
instance (Applicative m, Monad m) => Applicative (MultiWriterT x m) where
pure = MultiWriterT . pure
(<*>) = ap
instance Monad m => Monad (MultiWriterT x m) where
return = MultiWriterT . return
k >>= f = MultiWriterT $ runMultiWriterTRaw k >>= (runMultiWriterTRaw.f)
instance MonadTrans (MultiWriterT x) where
lift = MultiWriterT . lift
#if MIN_VERSION_base(4,8,0)
instance (Monad m, ContainsType a c, Monoid a)
#else
instance (Monad m, ContainsType a c, Monoid a)
#endif
=> MonadMultiWriter a (MultiWriterT c m) where
mTell v = MultiWriterT $ do
x <- get
put $ setHListElem (getHListElem x `mappend` v) x
instance MonadFix m => MonadFix (MultiWriterT w m) where
mfix f = MultiWriterT $ mfix (runMultiWriterTRaw . f)
mGetRaw :: Monad m => MultiWriterT a m (HList a)
mGetRaw = MultiWriterT get
mPutRaw :: Monad m => HList s -> MultiWriterT s m ()
mPutRaw = MultiWriterT . put
mapMultiWriterT :: (m (a, HList w) -> m' (a', HList w))
-> MultiWriterT w m a
-> MultiWriterT w m' a'
mapMultiWriterT f = MultiWriterT . mapStateT f . runMultiWriterTRaw
runMultiWriterT :: (Monoid (HList w), Functor m) => MultiWriterT w m a -> m (a, HList w)
runMultiWriterTAW :: (Monoid (HList w), Functor m) => MultiWriterT w m a -> m (a, HList w)
runMultiWriterTWA :: (Monoid (HList w), Monad m) => MultiWriterT w m a -> m (HList w, a)
runMultiWriterTW :: (Monoid (HList w), Monad m) => MultiWriterT w m a -> m (HList w)
runMultiWriterT = runMultiWriterTAW
runMultiWriterTAW k = runStateT (runMultiWriterTRaw k) mempty
runMultiWriterTWA k = (\(a,b) -> (b,a)) `liftM` runStateT (runMultiWriterTRaw k) mempty
runMultiWriterTW k = execStateT (runMultiWriterTRaw k) mempty
runMultiWriterTNil :: Monad m => MultiWriterT '[] m a -> m a
runMultiWriterTNil_ :: Functor m => MultiWriterT '[] m a -> m ()
runMultiWriterTNil k = evalStateT (runMultiWriterTRaw k) HNil
runMultiWriterTNil_ k = void $ runStateT (runMultiWriterTRaw k) HNil
withMultiWriter :: (Monoid w, Monad m) => MultiWriterT (w ': ws) m a -> MultiWriterT ws m (a, w)
withMultiWriterAW :: (Monoid w, Monad m) => MultiWriterT (w ': ws) m a -> MultiWriterT ws m (a, w)
withMultiWriterWA :: (Monoid w, Monad m) => MultiWriterT (w ': ws) m a -> MultiWriterT ws m (w, a)
withMultiWriterW :: (Monoid w, Monad m) => MultiWriterT (w ': ws) m a -> MultiWriterT ws m w
withMultiWriter = withMultiWriterAW
withMultiWriterAW k = MultiWriterT $ do
w <- get
(a, w') <- lift $ runStateT (runMultiWriterTRaw k) (mempty :+: w)
case w' of x' :+: wr' -> do put wr'; return (a, x')
withMultiWriterWA k = (\(a,b) -> (b,a)) `liftM` withMultiWriterAW k
withMultiWriterW k = snd `liftM` withMultiWriterAW k
withMultiWriters :: forall w1 w2 m a
. (Monoid (HList w1), Monad m, HInit w1)
=> MultiWriterT (Append w1 w2) m a
-> MultiWriterT w2 m (a, HList w1)
withMultiWritersAW :: forall w1 w2 m a
. (Monoid (HList w1), Monad m, HInit w1)
=> MultiWriterT (Append w1 w2) m a
-> MultiWriterT w2 m (a, HList w1)
withMultiWritersWA :: forall w1 w2 m a
. (Monoid (HList w1), Monad m, HInit w1)
=> MultiWriterT (Append w1 w2) m a
-> MultiWriterT w2 m (HList w1, a)
withMultiWritersW :: forall w1 w2 m a
. (Monoid (HList w1), Monad m, HInit w1)
=> MultiWriterT (Append w1 w2) m a
-> MultiWriterT w2 m (HList w1)
withMultiWriters = withMultiWritersAW
withMultiWritersAW k = MultiWriterT $ do
w <- get
(a, ws') <- lift $ runStateT (runMultiWriterTRaw k) (hAppend (mempty :: HList w1) w)
let (o, w') = hSplit ws'
put w'
return $ (a, o)
withMultiWritersWA k = MultiWriterT $ do
w <- get
(a, ws') <- lift $ runStateT (runMultiWriterTRaw k) (hAppend (mempty :: HList w1) w)
let (o, w') = hSplit ws'
put w'
return $ (o, a)
withMultiWritersW k = MultiWriterT $ do
w <- get
ws' <- lift $ execStateT (runMultiWriterTRaw k) (hAppend (mempty :: HList w1) w)
let (o, w') = hSplit ws'
put w'
return $ o
inflateWriter :: (Monad m, Monoid w, ContainsType w ws)
=> WriterT w m a
-> MultiWriterT ws m a
inflateWriter k = do
(x, w) <- lift $ runWriterT k
mTell w
return x
instance (MonadState s m) => MonadState s (MultiWriterT c m) where
put = lift . put
get = lift $ get
state = lift . state
instance (MonadWriter w m) => MonadWriter w (MultiWriterT c m) where
writer = lift . writer
tell = lift . tell
listen = MultiWriterT .
mapStateT (liftM (\((a,w), w') -> ((a, w'), w)) . listen) .
runMultiWriterTRaw
pass = MultiWriterT .
mapStateT (pass . liftM (\((a, f), w) -> ((a, w), f))) .
runMultiWriterTRaw
instance MonadIO m => MonadIO (MultiWriterT c m) where
liftIO = lift . liftIO
instance (Functor m, Applicative m, MonadPlus m) => Alternative (MultiWriterT c m) where
empty = lift mzero
MultiWriterT m <|> MultiWriterT n = MultiWriterT $ m <|> n
instance MonadPlus m => MonadPlus (MultiWriterT c m) where
mzero = MultiWriterT $ mzero
MultiWriterT m `mplus` MultiWriterT n = MultiWriterT $ m `mplus` n
instance MonadBase b m => MonadBase b (MultiWriterT c m) where
liftBase = liftBaseDefault
instance MonadTransControl (MultiWriterT c) where
type StT (MultiWriterT c) a = (a, HList c)
liftWith f = MultiWriterT $ liftWith $ \s -> f $ \r -> s $ runMultiWriterTRaw r
restoreT = MultiWriterT . restoreT
instance MonadBaseControl b m => MonadBaseControl b (MultiWriterT c m) where
type StM (MultiWriterT c m) a = ComposeSt (MultiWriterT c) m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM