[英]How does the do notation in Monad mean in Haskell
考慮以下代碼段
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = state $ \(x:xs) -> (x, xs)
push :: Int -> State Stack ()
push a = state $ \xs -> ((), a:xs)
stackManip :: State Stack Int
stackManip = do
push 3
a <- pop
pop
正如我們所知,Monad 中的do notation
與>>=
運算符相同。 我們可以將此段重寫為:
push 3 >>= (\_ ->
pop >>= (\a ->
pop))
這個表達式的最終值與push 3
和第一個pop
無關,無論輸入什么,它都只返回pop
,所以不會先把值3入棧再pop,為什么會這樣?
感謝您的回復。 我在上面添加了缺少的代碼( Stack
、 push
和pop
),我想我已經弄清楚它是如何工作的。 理解這段代碼的關鍵是理解State s
monad的實現:
instance Monad (State s) where
return x = State $ \s -> (x, s)
(State h) >>= f = State $ \s -> let (a, newState) = h s
(State g) = f a
in g newState
>>=
do 的整個實現是將狀態傳遞給函數h ,計算其新狀態並將新狀態傳遞給f 中隱含的函數g ,從而獲得更新的狀態。 所以實際上狀態已經隱式改變了。
由於 Monad 法則,您的代碼相當於
stackManip :: State Stack Int
stackManip = do
push 3
a <- pop -- a == 3
r <- pop
return r
所以你壓入 3,彈出它,忽略彈出的 3,彈出另一個值並返回它。
Haskell 只是另一種編程語言。 你是程序員。 編譯器是否跳過無關緊要的指令取決於它,並且無論如何都是不可觀察的(除非通過檢查編譯器生成的代碼,或在執行代碼時測量 CPU 的熱量,但在服務器中可能有點困難)極圈以外的農場)。
Haskell 中的 Monad 有時被稱為“可編程分號”。 總的來說,我覺得這不是一個特別有用的短語,但它確實捕捉到了用 Haskell 的do
表示法編寫的表達式具有命令式程序的味道的方式。 特別是do
塊中的“語句”組合方式取決於所使用的特定 monad。 因此,“可編程分號”——連續的“語句”(在許多命令式語言中用分號分隔)組合在一起的方式可以通過使用不同的 monad 來改變(“編程”)。
由於do
表示法實際上只是使用>>=
運算符從其他人構建表達式的語法糖,因此每個 monad 的>>=
實現決定了它的“特殊行為”是什么。
例如, Monad
例如Maybe
允許一個,作為一個粗略的說明中,與工作Maybe
值,如同它們是實際值的基礎類型的,同時確保,如果一個非值(即, Nothing
)發生在任何點,計算短路和Nothing
將是整體結果。
對於列表 monad,每一行實際上都被“執行”多次(或沒有)——對列表中的每個元素執行一次。
對於State s
monad 的值,這些本質上是s -> (a, s)
類型s -> (a, s)
“狀態操作函數” - 它們采用初始狀態,並從中計算出新狀態以及某種類型的輸出值a
。 >>=
實現 - “分號” - 在這里*所做的只是確保,當一個函數f :: s -> (a, s)
后跟另一個g :: s -> (b, s)
,結果函數將f
應用於初始狀態,然后將g
應用於從f
計算出的狀態。 它基本上只是函數組合,稍作修改,以便還允許我們訪問類型不一定與狀態相關的“輸出值”。 這允許人們在do
塊中一個接一個地列出各種狀態操作函數,並知道每個階段的狀態正是由前幾行放在一起計算的狀態。 這反過來又允許一種非常自然的編程風格,您可以在其中給出連續的“命令”來操作狀態,但實際上不會進行破壞性更新,或者以其他方式脫離純函數和不可變數據的世界。
*嚴格來說,這不是>>=
而是>>
,一個從>>=
派生的操作,但忽略了輸出值。 您可能已經注意到,在示例中,我給出了f
輸出的a
值被完全忽略了 - 但是>>=
允許檢查該值並確定下一步要執行的計算。 在do
表示法中,這意味着先寫a <- f
然后再使用a
。 這實際上是將 Monad 與它們功能較弱但仍然很重要的表親(特別是 Applicative functor)區分開來的關鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.