Haskell do notation 的正經定義

永遠在用do,永遠記不得do作爲一個語法糖,對應的真實語法是什麼。寫一篇博文記一下。

-- | ----------------------------------------------------
-- | (1) do { m1 } ==> m1
-- | (2) do { m1; m2 } ==> m1 >> do { m2 }
-- | (3) do { let s1; m1 s1 } ==> let s1 in do { m1 s1 }
-- | (3’) do { let s1; m1 s1 } ==> do { m1 s1 } where s1
-- | (4) do { x <- m1; m2 x } ==> m1 >>= (\x -> do { m2 x } )
-- | (5) do { x <- m1; let s = f x; m2 s } ==> do { s <- f <$> m1; m2 s }
-- | (6) do { x <- m1; y <- m2; let s = f x y; m3 s } ==> do { s <- f <$> m1 <*> m2; m3 s }
-- | (7) let s1; let s2 ==> let (s1; s2)
-- | (8) (\x -> f x) ==> f
-- | ----------------------------------------------------

其中的前六條就是記下來備忘的。(來源:此文 & 建議閱讀此文!)
簡單來說,有三種情況:

  • 單獨的表達式,可以理解成執行相應內容,但不保留結果。
  • <-表達式,可以理解成把套Monad的值賦給箭頭左邊的名字,但此名字在使用時可以視爲純值。
  • let表達式,可以理解爲正常的let-in表達式。
  • 最後:最後一行是返回值,決定了返回的是誰,類型是什麼。

另外,如果用大括號控制do的範圍,記得在每句話後加分號。而如果用縮進來控制,let有時會出現一些玄學問題,這是Haskell在實現時,多字母關鍵字(比如let,where等)面臨的一個通病。建議少用let而多用let-in或其他方式。如果用let的話,下一行及之後的縮進要比let還深。

備忘

do-日語
do-漢語

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章