2012-01-04 38 views
10

Đã được xác nhận trong số Validations in Haskell việc sử dụng số Writer đảm bảo nối liên kết phù hợp. Tuy nhiên, ví dụ này có vẻ hiển thị khác. Câu trả lời đúng là gì?Writer Monad có đảm bảo kết nối đúng không?

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

Tạo:

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

+1 cho ví dụ đơn giản về cách sử dụng và triển khai 'showsPrec'. –

+0

Điều thú vị là, nếu bạn thay thế 'replicateM_' bằng' replicateM', đầu ra sẽ trở thành '" Hello "++ (" World "++ (" World "++" "++" ") ++" ") ++" ! "' – pat

+3

Đó là sự khác biệt giữa 'sequence' và' sequence_': 'sequence = foldr (liftM2 (:)) (return [])' nhưng 'sequence_ = foldr (>>) (return())'; trước đây tạo ra nhiều ràng buộc hơn bởi vì nó làm việc với kết quả. – ehird

Trả lời

7

Vâng, đây thực sự là không đúng sự thật. Từ 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) 

Vì vậy, các chuỗi mappend s sẽ phản ánh các chuỗi (>>=) s.

1

Writer [a] không đảm bảo nối liên kết phù hợp, nhưng bạn có thể nhận được sự liên kết phù hợp phải được đảm bảo với Writer (Endo [a]).

Các vấn đề liên quan