haskell - 缩进操作符

标签 haskell monads indentation operator-precedence backticks

hindent 将我的代码更改为:

do download i inputFile
   onException
     (callProcess (List.head args) (List.tail args))
     (removeFileIfExists name)
   `finally` removeFileIfExists inputFile

我无法确定 finally 是否适用于 do block 的其余部分,或者仅适用于 onException 开始的状态。根据this ,

If you see something unexpected in a list, like where, insert a closing brace before instead of a semicolon.

我不确定该规则是否适用于此。

`finally` 是否适用于 do 的其余部分,或者仅适用于最后一条语句?为什么?

最佳答案

我们可以使用 GHCi 来查找:写作

Prelude> let f = (>>)
Prelude> :{
Prelude| do print 5
Prelude|    print 4
Prelude|    `f` print 3
Prelude|    print 2
Prelude| :}

导致以下类型错误(不是解析错误!)

<interactive>:12:8: error:
    • Couldn't match expected type ‘(() -> IO ()) -> Integer -> IO b’
                  with actual type ‘IO ()’
    • The function ‘print’ is applied to three arguments,
      but its type ‘Integer -> IO ()’ has only one
      In the second argument of ‘f’, namely ‘print 3 print 2’
      In the expression:
        do { print 5;
             print 4 }
        `f` print 3 print 2

查看列表行,我们发现 GHCi 是如何解析代码的,该代码是用明确的大括号和分号打印的。

在那里,我们看到 `f` 部分关闭do block !这使得整个 do block 成为 f 的第一个参数。此外,接下来的行不再位于 block 中,现在形成单个表达式 print 4 print 2,用作 f 的第二个参数。这会触发类型错误,因为它使用三个参数调用 print

确实,大括号 } 被插入在 `f` 之前,因为OP提到的规则:当 block 中的某些内容无法解析时,我们添加 } 并继续。

总结一下,如果 `f` 缩进 more,则该 block 将被解析为

do print 5
   print 4 `f` print 3
   print 2

如果`f`缩进前一行,或者,则该 block 将被解析为

(do { print 5
    ; print 4 }) `f` print 3 print 2

我建议避免像前一行一样缩进 `f`:最好少缩进,这样即使对于人类读者来说,解析也会变得显而易见。

关于haskell - 缩进操作符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48984756/

相关文章:

haskell - 点自由一元表达式

haskell - 状态和错误 monad 堆栈,错误时状态回滚

python-3.x - Python3 IndentationError : expected an indented block - should not throw this

javascript - Eclipse 可以在 JavaScript 数组初始化程序之后用 1 个制表符缩进新行吗?

haskell - 使用 Haskell 的数学表达式的邻域

haskell - (!!) 整数溢出运算符

haskell - 在这个回合制游戏中使用 Reader monad 是否正确?

exception - Haskell 中的安全应用

scala - 将 A => M[B] 转换为 M[A => B]

vim - 阻止vim删除空行上的缩进