[英]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.