monad是一個「事物」,它需要一個上下文(我們稱之爲m),以及哪個「產生」了一個值,同時仍尊重monad法則。我們可以從單子的「內部」和「外部」的角度來考慮這一點。單子法告訴我們如何處理「往返」 - 去外面然後再回來。特別是,法律告訴我們m(m a)與(m a)基本上是相同的類型。
重點是monad是這種往返事物的概括。 (m(m a))'加入(m a)'中,並且(>> =)從monad中拉出一個值並將一個函數應用到monad中。換句話說,它將函數(f :: a - > m b)應用於a(m a)中 - 這將產生一個(m(m b)),然後通過連接壓縮以獲得我們的(m b)。
那麼這與'get'和對象有什麼關係呢?
那麼,記號使我們起來,以便計算的結果在我們的monad中。並且(< - )讓我們將從monad中取出一個值,以便我們可以將它綁定到一個函數,同時名義上還在monad中。因此,例如:
doStuff = do
a <- get
b <- get
return $ (a + b)
請注意a和b是純的。他們是「外」的,因爲我們真的在裏面偷看。但是現在我們已經在monad之外獲得了一個價值,我們需要對它做一些事情(+),然後把它放回monad中。
這是啓發性的符號的只是一點點,但如果我們能做到這一點可能是好的:
doStuff = do
a <- get
b <- get
(a + b) -> (\x -> return x)
真正強調的背部和中闡述它。當你完成一個monad動作時,你必須在的位於該表的右列,因爲當動作完成時,將會調用'join'來平鋪圖層。 (至少在概念上)
哦,對,對象。顯然,OO語言基本上是以某種IO單元生活和呼吸的。但我們實際上可以再分解一些。當您運行的線沿線的東西:
x = foo.bar.baz.bin()
你基本上是運行一個單子轉換棧,這需要一個IO背景下,其產生的foo的背景下,其產生的酒吧背景下,其產生的巴茲背景下,這產生一個bin上下文。然後運行時系統根據需要多次「加入」這個東西。請注意,這個想法與「調用堆棧」有何關係。事實上,這就是爲什麼它在haskell方面被稱爲「monad變壓器堆棧」。它是一堆monadic上下文。
代碼不是「調用」得到的。 「get」不是一個函數,它是一個多態值:http://hackage.haskell.org/packages/archive/transformers/latest/doc/html/Control-Monad-Trans-State-Lazy.html#v:得到 –
謝謝,這實際上是我的一個主要困惑點。對於來自面向對象領域的人來說,這幾乎是一個不幸的名字,其中類通常具有「getThis」和「getThat」方法。我只是假設由於「get」是一個動詞,它必須是一個函數。 –
即使在OO土地上也不是那麼簡單。特別是因爲OO獲取器不是函數 - 它們實際上更接近於多態值,就像Haskell的get一樣。不同之處在於OO語言中的monad將該值附加到對象上,而我們將該值附加到具有任意語義的任意monad上。我會做出解釋,解釋我的意思。 – nomen