Here is the code from Control.Monad.Trans.Writer.Strictthat defined listenand pass:
listen :: (Monoid w, Monad m) => WriterT w m a -> WriterT w m (a, w)
listen m = WriterT $ do
(a, w) <- runWriterT m
return ((a, w), w)
pass :: (Monoid w, Monad m) => WriterT w m (a, w -> w) -> WriterT w m a
pass m = WriterT $ do
((a, f), w) <- runWriterT m
return (a, f w)
WriterT , Writer , Writer type Writer w = WriterT w Identity, Identity monad (<- >>=) , , :
listen :: (Monoid w) => Writer w a -> Writer w (a, w)
listen m = Writer $
let (a, w) = runWriter m
in ((a, w), w)
pass :: (Monoid w) => Writer w (a, w -> w) ->ใWriter w a
pass m = Writer $
let ((a, f), w) = runWriter m
in (a, f w)
, listen , Writer Writer, pass Writer.
, Writer [String] , :
deleteOn :: (Monoid w) => (w -> Bool) -> Writer w a -> Writer w a
deleteOn p m = pass $ do
(a, w) <- listen m
if p w
then return (a, id)
else return (a, const mempty)
-- Or pass alone
deleteOn' :: (Monoid w) => (w -> Bool) -> Writer w a -> Writer w a
deleteOn' p m = pass $ do
a <- m
return (a, (\w -> if p w then mempty else w))
logTwo :: Writer [String] ()
logTwo = do
deleteOn ((> 5) . length . head) $ tell ["foo"]
deleteOn ((> 5) . length . head) $ tell ["foobar"]
{-
*Main> runWriter logTwo
((),["foo"])
-}