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 Intpop = do (x:xs) &<- getput xs
return xget 返回的明明是一個被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秋納筆試