簡體   English   中英

僅使用monadic綁定語法表示阻止

[英]Expressing do block using only monadic bind syntax

據我所知, do在Haskell塊都只是某種對一元的綁定運營商的語法糖。 例如,一個人可以轉換

main = do f <- readFile "foo.txt"
          print f
          print "Finished"

main = readFile "foo.txt" >>= print >> print "Finished"

都可以do塊轉換的綁定語法? 例如,這個塊多次使用f

main = do f <- readFile "foo.txt"
          print $ "prefix " ++ f
          print $ f ++ " postfix"

假設我們在IO monad中,則不可能簡單地執行readFile計算兩次。 如何使用綁定語法表示此示例(如果可能的話)?

我認為使用Control.Monad不是解決方案,因為它在內部使用do塊。

我認為可以使用箭頭表示這一點(使用&&& ) - 也許這種情況下只有箭頭可以用作monads的推廣

請注意,這個問題不是關於上面的特殊示例,而是關於計算結果在print等monadic表達式中多次使用的一般情況。

是的,所有這些都可以轉換為綁定語法; 實際上,它們是由編譯器在內部轉換的。

我希望你的例子的這個翻譯給你提示:

main = readFile "foo.txt" >>= \f ->
       (print $ "prefix " ++ f) >>
       (print $ f ++ " postfix")

報告提供了從do語法到內核Haskell的完整翻譯:

在消除空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} 

省略號“...”代表編譯器生成的錯誤消息,傳遞給失敗,最好給出一些模式匹配失敗位置的指示; 函數>>,>> =和fail是Monad類中的操作,如Prelude中所定義; 而ok是一個新的標識符。

所以你的例子就是這樣翻譯的:

do f <- readFile "foo.txt"
   print $ "prefix " ++ f
   print $ f ++ " postfix"
=
let ok f = do print $ "prefix " ++ f
              print $ f ++ " postfix"
    ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> do print $ f ++ " postfix"
    ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> (print $ f ++ " postfix")
    ok _ = fail "..."
in readFile "foo.txt" >>= ok

這個版本沒有do塊,但看起來不自然。 但我們可以應用等式推理和我們所知道的任何優化。 因此,例如,觀察了ok _ = fail "..."子句死碼,我們可以inlike ok ,像這樣:

 =
 readFile "foo.txt" >>= \f ->
 (print $ "prefix " ++ f) >>
 (print $ f ++ " postfix")

所有do塊可以機械地翻譯成代碼,而無需do這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM