haskell 中左箭頭到底做了什麼?

最近學Haskell中的Monad一章,裡面講到Monad運算的do記法。發現對於不同類型的Monad,左箭頭&<-的工作方式完全不同,這讓我有些疑惑。

比如List a作為Monad時,左箭頭會將List所有元素都做一次綁定然後返回所有結果的List。而Maybe作為Monad時,將Just x 下的x進行綁定。

我一直把Monad當做一種「容器」,左箭頭被理解為一種抽取操作,所以以上例子雖然不知其所以然,也好歹能知其然。但是看到State Monad下的一個例子

get = state $ s-&>(s,s)

pop :: State Stack Int

pop = do

(x:xs) &<- get

put xs

return x

get 返回的明明是一個被state包裹的序對生成器,為何提取出來後只剩下了表示計算結果部分的(x:xs)?


不是&<-的工作方式不同。do-notation的翻譯規則是固定的:

Translation: Do expressions satisfy these identities, which may be used as a translation into the kernel, after eliminating empty stmts:

do {e} = e
do {e;stmts} = e &>&> do {stmts}
do {p &<- e; stmts} = let ok p = do {stmts} ok _ = fail "..." in e &>&>= ok
do {let decls; stmts} = let decls in do {stmts}

The ellipsis "..." stands for a compiler-generated error message, passed to fail, preferably giving some indication of the location of the pattern-match failure; the functions &>&>, &>&>=, and fail are operations in the class Monad, as defined in the Prelude; and ok is a fresh identifier.

參考https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.14

然後具體到State monad的get操作。假設你談論的是這個簡化版的State monad:

newtype State s a = State { runState :: s -&> (a,s) }

instance Monad (State s) where
return a = State $ s -&> (a,s)
m &>&>= f = State $ s -&> let (a,s) = runState m s in runState (f a) s

-- missing Functor/Applicative instances for brevity

get :: State s s
get = State $ s -&> (s,s)

put :: s -&> State s ()
put s = State $ \_ -&> ((),s)

看這個&>&>=的定義,綁定到&<-左邊的pattern的,就是&<-右邊對應的State s a中的a,帶狀態的計算結果。&<-右邊是get,看get的類型,自然綁定過去的就是當前狀態了。。


左箭頭只是個語法糖,關鍵是monadic law


https://www.cs.indiana.edu/~cswords/monads.pdf


do

x左箭頭y

不是

y &>&>=(x -&> …)

的語法糖嗎?

至少我是這樣理解的。。

列表推導式中左箭頭又是do 的語法糖。。


&<-其實就是把右邊的計算語境bind到左邊的變數上


推薦閱讀:

有沒有對Haskell中理解monad比較好的代碼例子?
Haskell做APP後端開發能有性能上的飛躍么?
Haskell用在工程項目中有什麼優勢?
ZJU Lambda2017秋納筆試

TAG:函數式編程 | monad | Haskell |