# New monads/LazyWriterT

### From HaskellWiki

< New monads(Difference between revisions)

(Add Lazy version of WriterT (handy for Control.Monad.ST.Lazy)) |
BrettGiles (Talk | contribs) m (NewMonads/LazyWriterT moved to New monads/LazyWriterT) |

## Revision as of 15:58, 7 October 2006

This came up on the mailing list: Why is WriterT never lazy? The answer is it does not use lazy patterns with "~". So here is a more useful NewMonads/LazyWriterT that add two "~" to the definition of (>>=) and renames WriterT to LazyWriterT.

This is very very handy when (Control.Monad.ST.Lazy) is the transformed Monad.

{-# OPTIONS_GHC -fglasgow-exts #-} module Main where -- LazyWriterT, copied from http://darcs.haskell.org/packages/mtl/Control/Monad/Writer.hs import Control.Monad.Writer import Control.Monad.Reader import Control.Monad.Fix import Control.Monad.Trans newtype LazyWriterT w m a = LazyWriterT { runLazyWriterT :: m (a, w) } instance (Monad m) => Functor (LazyWriterT w m) where fmap f m = LazyWriterT $ do (a, w) <- runLazyWriterT m return (f a, w) instance (Monoid w, Monad m) => Monad (LazyWriterT w m) where return a = LazyWriterT $ return (a, mempty) m >>= k = LazyWriterT $ do ~(a,w) <- runLazyWriterT m ~(b,w') <- runLazyWriterT (k a) return (b, w `mappend` w') fail msg = LazyWriterT $ fail msg instance (Monoid w, MonadPlus m) => MonadPlus (LazyWriterT w m) where mzero = LazyWriterT mzero m `mplus` n = LazyWriterT $ runLazyWriterT m `mplus` runLazyWriterT n instance (Monoid w, MonadFix m) => MonadFix (LazyWriterT w m) where mfix m = LazyWriterT $ mfix $ \ ~(a, _) -> runLazyWriterT (m a) instance (Monoid w, Monad m) => MonadWriter w (LazyWriterT w m) where tell w = LazyWriterT $ return ((), w) listen m = LazyWriterT $ do (a, w) <- runLazyWriterT m return ((a, w), w) pass m = LazyWriterT $ do ((a, f), w) <- runLazyWriterT m return (a, f w) instance (Monoid w) => MonadTrans (LazyWriterT w) where lift m = LazyWriterT $ do a <- m return (a, mempty) instance (Monoid w, MonadIO m) => MonadIO (LazyWriterT w m) where liftIO = lift . liftIO instance (Monoid w, MonadReader r m) => MonadReader r (LazyWriterT w m) where ask = lift ask local f m = LazyWriterT $ local f (runLazyWriterT m) execLazyWriterT :: Monad m => LazyWriterT w m a -> m w execLazyWriterT m = do (_, w) <- runLazyWriterT m return w mapLazyWriterT :: (m (a, w) -> n (b, w')) -> LazyWriterT w m a -> LazyWriterT w' n b mapLazyWriterT f m = LazyWriterT $ f (runLazyWriterT m)