ether-0.1.0.0: src/Control/Monad/Ether/Writer/Class.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- | See "Control.Monad.Writer.Class".
module Control.Monad.Ether.Writer.Class
( MonadWriter(..)
, listens
, censor
) where
import Data.Proxy (Proxy(Proxy))
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Ether.Writer hiding (writer, tell, listen, pass)
import qualified Control.Monad.Trans.Ether.Reader as R
import qualified Control.Monad.Trans.Ether.State.Lazy as S.L
import qualified Control.Monad.Trans.Ether.State.Strict as S.S
import qualified Control.Monad.Trans.Ether.Except as E
import qualified Control.Monad.Trans.Ether.Writer as W
import qualified Control.Ether.Util as Util
-- for mtl instances
import qualified Control.Monad.Trans.Except as Trans.E
import qualified Control.Monad.Trans.Identity as Trans.I
import qualified Control.Monad.Trans.Maybe as Trans.M
import qualified Control.Monad.Trans.Reader as Trans.R
import qualified Control.Monad.Trans.State.Lazy as Trans.S.Lazy
import qualified Control.Monad.Trans.State.Strict as Trans.S.Strict
import qualified Control.Monad.Trans.Writer.Lazy as Trans.W.Lazy
-- | See 'Control.Monad.Writer.MonadWriter'.
class (Monoid w, Monad m) => MonadWriter tag w m | m tag -> w where
{-# MINIMAL (writer | tell), listen, pass #-}
-- | Embed a simple writer action.
writer :: proxy tag -> (a, w) -> m a
writer t ~(a, w) = do
tell t w
return a
-- | Append a value to the accumulator within the monad.
tell :: proxy tag -> w -> m ()
tell t w = writer t ((),w)
-- | Execute an action and add its accumulator
-- to the value of the computation.
listen :: proxy tag -> m a -> m (a, w)
-- | Execute an action which returns a value and a function,
-- and return the value, applying the function to the accumulator.
pass :: proxy tag -> m (a, w -> w) -> m a
-- | Execute an action and add the result of applying the given function to
-- its accumulator to the value of the computation.
listens :: MonadWriter tag w m => proxy tag -> (w -> b) -> m a -> m (a, b)
listens t f m = do
~(a, w) <- listen t m
return (a, f w)
-- | Execute an action and apply a function to its accumulator.
censor :: MonadWriter tag w m => proxy tag -> (w -> w) -> m a -> m a
censor t f m = pass t $ do
a <- m
return (a, f)
instance {-# OVERLAPPING #-} (Monoid w, Monad m) => MonadWriter tag w (WriterT tag w m) where
writer = W.writer
tell = W.tell
listen = W.listen
pass = W.pass
instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (WriterT tag' w' m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = W.liftListen Proxy (listen t)
pass t = W.liftPass Proxy (pass t)
-- Instances for other tagged transformers
instance (MonadWriter tag w m) => MonadWriter tag w (R.ReaderT tag' r m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = R.mapReaderT Proxy (listen t)
pass t = R.mapReaderT Proxy (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (E.ExceptT tag' e m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = E.liftListen Proxy (listen t)
pass t = E.liftPass Proxy (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (S.L.StateT tag' e m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = S.L.liftListen Proxy (listen t)
pass t = S.L.liftPass Proxy (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (S.S.StateT tag' e m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = S.S.liftListen Proxy (listen t)
pass t = S.S.liftPass Proxy (pass t)
-- Instances for mtl transformers
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.E.ExceptT e m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.E.liftListen (listen t)
pass t = Trans.E.liftPass (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.I.IdentityT m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.I.mapIdentityT (listen t)
pass t = Trans.I.mapIdentityT (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.M.MaybeT m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.M.liftListen (listen t)
pass t = Trans.M.liftPass (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.R.ReaderT r m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.R.mapReaderT (listen t)
pass t = Trans.R.mapReaderT (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Lazy.StateT s m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.S.Lazy.liftListen (listen t)
pass t = Trans.S.Lazy.liftPass (pass t)
instance (MonadWriter tag w m) => MonadWriter tag w (Trans.S.Strict.StateT s m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Trans.S.Strict.liftListen (listen t)
pass t = Trans.S.Strict.liftPass (pass t)
instance (Monoid w', MonadWriter tag w m) => MonadWriter tag w (Trans.W.Lazy.WriterT w' m) where
writer t = lift . writer t
tell t = lift . tell t
listen t = Util.liftListen_WriterT (listen t)
pass t = Util.liftPass_WriterT (pass t)