2015-11-23 47 views
1

我正在學習Writer Monad的書「學習你一個Haskell」。Writer Monad的理解示例

這是一段代碼:

import Control.Monad.Writer 

logNumber :: Int -> Writer [String] Int 
logNumber num = writer (num, ["Got number: " ++ show num]) 

multWithLog :: Writer [String] Int 
multWithLog = do 
    a <- logNumber 3 
    b <- logNumber 5 
    return (a * b) 

當運行multWithLog,這是結果:

*Main> runWriter multWithLog 
(15,["Got number: 3","Got number: 5"]) 

在此行:

a <- logNumber 3 
b <- logNumber 5 

這是很容易看到那a = 3b = 5,因爲他們都在倍增return函數。

我不明白的是爲什麼這些值是35ab是否應該包含在Writer Monad中的值?在這種情況下元組?

例如,這是與Maybe單子,ab35

do 
    a <- Just 3 
    b <- Just 5 
    return (a * b) 

在這種情況下,對我來說很有意義,因爲ab收到內部Just內容。但以最初的例子,ab只接收部分值。

+0

當您在'Writer' monad中執行'x <-e'時,'x'通常不會捕獲編寫器狀態。您可以將logNumber重寫爲「logNumber num = tell」...「>> return num」 - 這是一個計算結果,它產生的數字與它給出的數字相同,但作爲副作用「記錄」了一個字符串。當你「綁定」你正在訪問「返回」的值 - 這只是數字。你可以用'listen'得到想要的行爲:'(x,loggedString)< - listen $ logNumber 3'。 – user2407038

回答

2

很容易看出a = 3和b = 5,因爲它們都在返回函數上相乘。我不明白的是爲什麼這些值是3和5.不應該a和b是Writer Monad中包含的值嗎?在這種情況下元組?

不,我認爲回答這個最簡單的方法是隻需實現Writer型並研究其Monad類的實例:

newtype Writer w a = Writer { runWriter :: (a, w) } 

instance Functor (Writer w) where 
    fmap f (Writer (a, w)) = Writer (f a, w) 

instance Monoid w => Applicative (Writer w) where 
    pure a = Writer (a, mempty) 
    Writer (f, w) <*> Writer (a, w') = Writer (f a, w <> w') 

instance Monoid w => Monad (Writer w) where 
    return = pure 
    Writer (a, w) >>= f = let (b, w') = runWriter (f a) 
         in Writer (b, w <> w') 

tell :: w -> Writer w() 
tell w = Writer ((), w) 

正如你可以在實例方法見>>=,功能f適用於a值,而不是整個元組。語法a <- logNumber 3使用>>=解除綁定,因此綁定到a的值將是Writer所包含的元組的第一個元素。

2

「包含在monad中的想法有點模糊。它有點作品,但並不嚴格。

真的,一個monad本身不包含「包含」任何東西。這是not actually a spacesuit or burrito,你知道...

Writer的情況下,你能說清楚,這是一個型其值同時​​包含日誌段和計算,結果。後者是您可能會解釋的單子的「內容」,您可以使用a <-來檢索。但總的來說,根本不需要任何這樣的內容。

事實上,留在你的Maybe例如:

do a <- Just 3 
    Nothing 
    b <- Just 5 
    return (a * b) 

在這種情況下,Nothing 「中斷」計算,所以Just 5沒有永遠能值5注入a

要記住的事情是,如果action :: M T一些單子M,然後

do 
    ... 
    a <- action 

可以給aT類型的值。(在你的榜樣,MWriter [String]TInt,所以a只能有型Int。)

無論是實際發生的,多久,這裏的值來自與意味着什麼取決於具體的單子。不過,monad laws可以告訴你很多關於整個計算的行爲。但是,在瞭解monad時,最好忘掉所有這些,只需看看許多不同的例子,並自己和monad打交道,在某些時候你會得到一個直覺。 Don't try too hard to 「understand」 monads through analogies

3

在這種情況下,對我來說很有意義,因爲ab收到內部Just內容。但以最初的例子,ab只接收部分值。

這個描述沒有什麼錯,但我們也可以用另一種方式來看待這種情況。在...

a <- Just 3 

...我們也可以說,a只接收的Just 3部分 - Just包裝沒有做到這一點。從這一點來看,與什麼發生了......

a <- writer (3, ["Got number: " ++ show 3]) 

...頗爲相似:a只接收3值。該[String]註解,如此說來,留在後臺,讓mappend編入彼此由一元的綁定,就像(>>=)結合Maybe這麼說JustJustJustNothing與任何給Nothing