仅使用monadic绑定语法表示阻止

Uli*_*ler 5 monads haskell scope do-notation

据我所知,doHaskell中的块只是monadic绑定运算符的某种语法糖.例如,一个人可以转换

main = do f <- readFile "foo.txt"
          print f
          print "Finished"
Run Code Online (Sandbox Code Playgroud)

main = readFile "foo.txt" >>= print >> print "Finished"
Run Code Online (Sandbox Code Playgroud)

是否可以将所有do块转换为绑定语法?例如,f多次使用此块的情况如何:

main = do f <- readFile "foo.txt"
          print $ "prefix " ++ f
          print $ f ++ " postfix"
Run Code Online (Sandbox Code Playgroud)

假设我们在IO monad中,则不可能简单地执行readFile两次计算.如何使用绑定语法表示此示例(如果可能的话)?

我认为使用Control.Monad不是解决方案,因为它在内部使用do块.

我认为可以使用箭头(使用&&&)表达这一点- 也许这只是一个箭头可以用作monads的推广的情况

请注意,这个问题不是关于上面的特殊示例,而是关于在monadic表达式中多次使用计算结果的一般情况print.

Mig*_*Mit 11

是的,所有这些都可以转换为绑定语法; 实际上,它们是由编译器在内部转换的.

我希望你的例子的这个翻译给你提示:

main = readFile "foo.txt" >>= \f ->
       (print $ "prefix " ++ f) >>
       (print $ f ++ " postfix")
Run Code Online (Sandbox Code Playgroud)


Dan*_*ner 7

报告提供了从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}
Run Code Online (Sandbox Code Playgroud)

省略号“ ...”代表编译器生成的错误消息,传递给失败,最好给出模式匹配失败位置的指示;函数>>,>> =和fail是在Pread中定义的Monad类中的操作;好的是一个新的标识符。

因此,您的示例是这样翻译的:

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
Run Code Online (Sandbox Code Playgroud)

这个版本没有do障碍,但看起来不是很自然。但是我们可以应用方程式推理以及我们知道的任何优化。因此,例如,观察该ok _ = fail "..."子句是无效代码,我们可能ok像这样:

 =
 readFile "foo.txt" >>= \f ->
 (print $ "prefix " ++ f) >>
 (print $ f ++ " postfix")
Run Code Online (Sandbox Code Playgroud)

do无需do这种方式,可以将所有块机械地翻译为代码。