Помогает ли писатель Монада правильную ассоциативную конкатенацию?
В Утверждения в Haskell утверждалось, что использование Writer
гарантирует право-ассоциативную конкатенацию. Однако, этот пример, похоже, показывает обратное. Какой правильный ответ?
{-# 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
Выдает:
"Hello" ++ ("World" ++ "World" ++ "") ++ "!"
Ответы
Ответ 1
Да, это действительно неверно. Из исходного кода:
m >>= k = WriterT $ do
~(a, w) <- runWriterT m
~(b, w') <- runWriterT (k a)
return (b, w `mappend` w')
...
-- | @'tell' [email protected] is an action that produces the output @[email protected]
tell :: (Monoid w, Monad m) => w -> WriterT w m ()
tell w = WriterT $ return ((), w)
Таким образом, цепочка mappend
будет отражать цепочку (>>=)
s.
Ответ 2
Writer [a]
не гарантирует право-ассоциативную конкатенацию, но вы можете получить гарантированную право-ассоциативную конкатенацию с помощью Writer (Endo [a])
.