操作员做缩进

时间:2018-02-26 09:03:46

标签: 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块的其余部分,或仅适用于以onException开头的状态。根据{{​​3}},

  

如果您在列表中看到意外的内容,例如在哪里,请插入一个   关闭括号,而不是分号。

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

`finally`是否适用于do的其余部分,或仅仅是最后一个声明以及为什么?

1 个答案:

答案 0 :(得分:4)

我们可以找到使用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块!这使得整个do块成为f的第一个参数。此外,下一行不再在块中,现在形成单个表达式print 4 print 2,用作f的第二个参数。这会触发类型错误,因为它使用三个参数调用print

实际上,大括号}是在`f`之前插入的,因为OP提到的规则:当某个块没有解析时,我们添加}并继续。

总结一下,如果`f`缩进更多,则该块被解析为

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

如果`f`缩进上一行,或 less ,则该块将被解析为

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

我建议尽量避免缩进`f`与前一行完全一致:最好缩进它,这样即使对于人类读者来说,解析也很明显。