module Ether.Writer
(
MonadWriter
, writer
, tell
, listen
, pass
, listens
, censor
, Writer
, runWriter
, execWriter
, WriterT
, writerT
, runWriterT
, execWriterT
, LazyWriter
, runLazyWriter
, execLazyWriter
, LazyWriterT
, lazyWriterT
, runLazyWriterT
, execLazyWriterT
, MonadWriter'
, writer'
, tell'
, listen'
, pass'
, listens'
, censor'
, Writer'
, runWriter'
, execWriter'
, WriterT'
, writerT'
, runWriterT'
, execWriterT'
, LazyWriter'
, runLazyWriter'
, execLazyWriter'
, LazyWriterT'
, lazyWriterT'
, runLazyWriterT'
, execLazyWriterT'
, TAGGED
, WRITER
) where
import Control.Monad.Signatures (Listen, Pass)
import qualified Control.Monad.Trans.Lift.Listen as Lift
import qualified Control.Monad.Trans.Lift.Pass as Lift
import qualified Control.Monad.Writer.Class as T
import qualified Control.Monad.Writer.CPS as T.CPS
import qualified Control.Monad.Writer.Lazy as T.Lazy
import Data.Coerce
import Data.Functor.Identity
import Ether.Internal
import Ether.TaggedTrans
class (Monoid w, Monad m) => MonadWriter tag w m | m tag -> w where
writer :: (a, w) -> m a
writer ~(a, w) = a <$ tell @tag w
tell :: w -> m ()
tell w = writer @tag ((),w)
listen :: m a -> m (a, w)
pass :: m (a, w -> w) -> m a
instance
( Lift.LiftListen t
, Lift.LiftPass t
, Monad (t m)
, MonadWriter tag w m
, Monoid w
) => MonadWriter tag w (t m) where
writer = Lift.lift . writer @tag
tell = Lift.lift . tell @tag
listen = Lift.liftListen (listen @tag)
pass = Lift.liftPass (pass @tag)
listens :: forall tag w m a b . MonadWriter tag w m => (w -> b) -> m a -> m (a, b)
listens f m = do
~(a, w) <- listen @tag m
return (a, f w)
censor :: forall tag w m a . MonadWriter tag w m => (w -> w) -> m a -> m a
censor f m = pass @tag $ do
a <- m
return (a, f)
data WRITER
type instance HandleSuper WRITER w trans = Monoid w
type instance HandleConstraint WRITER w trans m =
T.MonadWriter w (trans m)
instance Monoid w => Handle WRITER w (T.CPS.WriterT w) where
handling r = r
instance Monoid w => Handle WRITER w (T.Lazy.WriterT w) where
handling r = r
instance
( Handle WRITER w trans
, Monad m, Monad (trans m)
) => MonadWriter tag w (TaggedTrans (TAGGED WRITER tag) trans m)
where
writer =
handling @WRITER @w @trans @m $
coerce (T.writer @w @(trans m) @a) ::
forall eff a . (a, w) -> TaggedTrans eff trans m a
tell =
handling @WRITER @w @trans @m $
coerce (T.tell @w @(trans m))
listen =
handling @WRITER @w @trans @m $
coerce (T.listen @w @(trans m) @a) ::
forall eff a . Listen w (TaggedTrans eff trans m) a
pass =
handling @WRITER @w @trans @m $
coerce (T.pass @w @(trans m) @a) ::
forall eff a . Pass w (TaggedTrans eff trans m) a
type Writer tag w = WriterT tag w Identity
type WriterT tag w = TaggedTrans (TAGGED WRITER tag) (T.CPS.WriterT w)
writerT :: forall tag w m a . (Functor m, Monoid w) => m (a, w) -> WriterT tag w m a
writerT = coerce (T.CPS.writerT @m @w @a)
runWriterT :: forall tag w m a . Monoid w => WriterT tag w m a -> m (a, w)
runWriterT = coerce (T.CPS.runWriterT @w @m @a)
runWriter :: forall tag w a . Monoid w => Writer tag w a -> (a, w)
runWriter = coerce (T.CPS.runWriter @w @a)
execWriterT :: forall tag w m a . (Monad m, Monoid w) => WriterT tag w m a -> m w
execWriterT = coerce (T.CPS.execWriterT @m @w @a)
execWriter :: forall tag w a . Monoid w => Writer tag w a -> w
execWriter = coerce (T.CPS.execWriter @w @a)
type LazyWriter tag w = LazyWriterT tag w Identity
type LazyWriterT tag w = TaggedTrans (TAGGED WRITER tag) (T.Lazy.WriterT w)
lazyWriterT :: forall tag w m a . m (a, w) -> LazyWriterT tag w m a
lazyWriterT = coerce (T.Lazy.WriterT @w @m @a)
runLazyWriterT :: forall tag w m a . LazyWriterT tag w m a -> m (a, w)
runLazyWriterT = coerce (T.Lazy.runWriterT @w @m @a)
runLazyWriter :: forall tag w a . LazyWriter tag w a -> (a, w)
runLazyWriter = coerce (T.Lazy.runWriter @w @a)
execLazyWriterT :: forall tag w m a . Monad m => LazyWriterT tag w m a -> m w
execLazyWriterT = coerce (T.Lazy.execWriterT @m @w @a)
execLazyWriter :: forall tag w a . LazyWriter tag w a -> w
execLazyWriter = coerce (T.Lazy.execWriter @w @a)
type Writer' w = Writer w w
runWriter' :: Monoid w => Writer' w a -> (a, w)
runWriter' = runWriter
execWriter' :: Monoid w => Writer' w a -> w
execWriter' = execWriter
type WriterT' w = WriterT w w
writerT' :: (Functor m, Monoid w) => m (a, w) -> WriterT' w m a
writerT' = writerT
runWriterT' :: Monoid w => WriterT' w m a -> m (a, w)
runWriterT' = runWriterT
execWriterT' :: (Monad m, Monoid w) => WriterT' w m a -> m w
execWriterT' = execWriterT
type LazyWriter' w = LazyWriter w w
runLazyWriter' :: LazyWriter' w a -> (a, w)
runLazyWriter' = runLazyWriter
execLazyWriter' :: LazyWriter' w a -> w
execLazyWriter' = execLazyWriter
type LazyWriterT' w = LazyWriterT w w
lazyWriterT' :: m (a, w) -> LazyWriterT' w m a
lazyWriterT' = lazyWriterT
runLazyWriterT' :: LazyWriterT' w m a -> m (a, w)
runLazyWriterT' = runLazyWriterT
execLazyWriterT' :: Monad m => LazyWriterT' w m a -> m w
execLazyWriterT' = execLazyWriterT
type MonadWriter' w = MonadWriter w w
writer' :: forall w m a . MonadWriter' w m => (a, w) -> m a
writer' = writer @w
tell' :: forall w m . MonadWriter' w m => w -> m ()
tell' = tell @w
listen' :: forall w m a . MonadWriter' w m => m a -> m (a, w)
listen' = listen @w
pass' :: forall w m a . MonadWriter' w m => m (a, w -> w) -> m a
pass' = pass @w
listens' :: forall w m a b . MonadWriter' w m => (w -> b) -> m a -> m (a, b)
listens' = listens @w
censor' :: forall w m a . MonadWriter' w m => (w -> w) -> m a -> m a
censor' = censor @w