2012-01-04 33 views
10

Se reclamó en Validations in Haskell que el uso de un Writer garantiza la concatenación asociativa derecha. Sin embargo, este ejemplo parece mostrar lo contrario. ¿Cuál es la respuesta correcta?¿Writer Monad garantiza la concatenación asociativa correcta?

{-# 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 

Produce:

"Hello" ++ ("World" ++ "World" ++ "") ++ "!" 
+0

+1 para el ejemplo simple de usar e implementar 'showsPrec'. –

+0

Curiosamente, si reemplaza 'replicateM_' con' replicateM', la salida se convierte en '" Hello "++ (" World "++ (" World "++" "++" ") ++" ") ++" ! "' – pat

+3

Es la diferencia entre 'sequence' y' sequence_': 'sequence = foldr (liftM2 (:)) (return [])' pero 'sequence_ = foldr (>>) (return())'; el primero genera más ataduras porque hace cosas con los resultados. – ehird

Respuesta

7

Sí, esto es de hecho falso. Desde el source code:

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) 

Así la cadena de mappend s será un reflejo de la cadena de (>>=) s.

1

Writer [a] no garantiza la concatenación de asociación correcta, pero puede obtener concatenación de asociación de derecha garantizada con Writer (Endo [a]).