It was claimed in Validations in Haskell that use of a Writer guarantees right-associative concatenation.  However, this example seems to show otherwise.  What's the correct answer?
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.Writer
import Data.String
data TM = TMempty
        | TMappend TM TM
        | TMfromString String
instance IsString TM where
  fromString = TMfromString
instance Monoid TM where
  mempty  = TMempty
  mappend = TMappend
instance Show TM where
  showsPrec d TMempty = showString "\"\""
  showsPrec d (TMfromString s) = showString $ show s
  showsPrec d (TMappend a b) = showParen (d > 0) $
    showsPrec 1 a .
    showString " ++ " .
    showsPrec 0 b
theWriter :: Writer TM ()
theWriter = do
  tell "Hello"
  replicateM_ 2 $ tell "World"
  tell "!"
main = print $ execWriter theWriter
Produces:
"Hello" ++ ("World" ++ "World" ++ "") ++ "!"
Yes, this is indeed untrue. From the source code:
m >>= k  = WriterT $ do
    ~(a, w)  <- runWriterT m
    ~(b, w') <- runWriterT (k a)
    return (b, w `mappend` w')
...
-- | @'tell' w@ is an action that produces the output @w@.
tell :: (Monoid w, Monad m) => w -> WriterT w m ()
tell w = WriterT $ return ((), w)
So the chain of mappends will mirror the chain of (>>=)s.
Writer [a] doesn't guarantee right-associative concatenation, but you can get guaranteed right-associative concatenation with Writer (Endo [a]).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With