缩进操作员
Operator on do indentation
hindent
将我的代码更改为:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
我无法确定 finally
是否适用于 do
块的其余部分,或者仅适用于 onException
开始的状态。根据this、
If you see something unexpected in a list, like where, insert a
closing brace before instead of a semicolon.
我不确定这条规则是否适用于此。
`finally`
是否适用于 do 的其余部分,还是仅适用于最后一条语句,为什么?
以下内容实际上并不是针对您发布的代码,而是针对您似乎要问的问题。它改为寻址以下代码:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
░`finally` removeFileIfExists inputFile
处理实际发布的代码,`finally`
的缩进不超过 download
和 onException
。我想说这是一种糟糕的风格:写的时候,一定要缩进 less,即
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
正如 Willem Van Onsem 评论的那样,函数应用程序 总是 优先于中缀应用程序。对于像 +
或 >>=
这样的“真正的中缀运算符”和 backtick-infixes 都是如此......如果事实上就优先级而言,这些类型的运算符之间没有明显的区别关注:对于所有中缀,优先级由固定性声明确定,例如
<a href="http://hackage.haskell.org/package/base-4.10.1.0/docs/src/GHC.Num.html#%2B" rel="nofollow noreferrer">infixl 6 +</a>
<a href="http://hackage.haskell.org/package/base-4.10.1.0/docs/src/Data.Foldable.html#elem" rel="nofollow noreferrer">infix 4 `elem`</a>
fixity是0..9范围内的数字,fixity可以是left-right-或non-associative。如果没有声明固定性(与大多数命名函数一样,而对于 symbol-infixes 强烈建议提供固定性声明),则使用默认值 infixl 9
,即基本上是您可以手动分配的最高合法固定性。
OTOH,函数应用程序是 always infixl 10
,即它比任何中缀都更紧密,无论它是如何声明的。因此,您的示例被解析为
do (download i inputFile)
( (onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name))
`finally`
(removeFileIfExists inputFile) )
我们可以用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 是如何解析代码的,该代码使用显式 braces-and-semicolons.
打印
在那里,我们看到 `f`
部分 关闭了 do
块!这使得整个 do
块成为 f
的第一个参数。此外,接下来的几行不再位于块中,现在形成单个表达式 print 4 print 2
,用作 f
的第二个参数。这会触发类型错误,因为它使用三个参数调用 print
。
确实,由于 OP 提到的规则,大括号 }
被插入到 `f`
之前:当某些内容未在块中解析时,我们添加 }
并继续。
总结一下,如果`f`
缩进more,则块被解析为
do print 5
print 4 `f` print 3
print 2
如果 `f`
缩进 为 前一行,或 less,该块被解析为
(do { print 5
; print 4 }) `f` print 3 print 2
我建议避免像前一行一样缩进 `f`
:最好少缩进,这样即使对于人类来说解析也变得显而易见 reader.
hindent
将我的代码更改为:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
我无法确定 finally
是否适用于 do
块的其余部分,或者仅适用于 onException
开始的状态。根据this、
If you see something unexpected in a list, like where, insert a closing brace before instead of a semicolon.
我不确定这条规则是否适用于此。
`finally`
是否适用于 do 的其余部分,还是仅适用于最后一条语句,为什么?
以下内容实际上并不是针对您发布的代码,而是针对您似乎要问的问题。它改为寻址以下代码:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
░`finally` removeFileIfExists inputFile
`finally`
的缩进不超过 download
和 onException
。我想说这是一种糟糕的风格:写的时候,一定要缩进 less,即
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
正如 Willem Van Onsem 评论的那样,函数应用程序 总是 优先于中缀应用程序。对于像 +
或 >>=
这样的“真正的中缀运算符”和 backtick-infixes 都是如此......如果事实上就优先级而言,这些类型的运算符之间没有明显的区别关注:对于所有中缀,优先级由固定性声明确定,例如
<a href="http://hackage.haskell.org/package/base-4.10.1.0/docs/src/GHC.Num.html#%2B" rel="nofollow noreferrer">infixl 6 +</a>
<a href="http://hackage.haskell.org/package/base-4.10.1.0/docs/src/Data.Foldable.html#elem" rel="nofollow noreferrer">infix 4 `elem`</a>
fixity是0..9范围内的数字,fixity可以是left-right-或non-associative。如果没有声明固定性(与大多数命名函数一样,而对于 symbol-infixes 强烈建议提供固定性声明),则使用默认值 infixl 9
,即基本上是您可以手动分配的最高合法固定性。
OTOH,函数应用程序是 always infixl 10
,即它比任何中缀都更紧密,无论它是如何声明的。因此,您的示例被解析为
do (download i inputFile)
( (onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name))
`finally`
(removeFileIfExists inputFile) )
我们可以用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 是如何解析代码的,该代码使用显式 braces-and-semicolons.
打印在那里,我们看到 `f`
部分 关闭了 do
块!这使得整个 do
块成为 f
的第一个参数。此外,接下来的几行不再位于块中,现在形成单个表达式 print 4 print 2
,用作 f
的第二个参数。这会触发类型错误,因为它使用三个参数调用 print
。
确实,由于 OP 提到的规则,大括号 }
被插入到 `f`
之前:当某些内容未在块中解析时,我们添加 }
并继续。
总结一下,如果`f`
缩进more,则块被解析为
do print 5
print 4 `f` print 3
print 2
如果 `f`
缩进 为 前一行,或 less,该块被解析为
(do { print 5
; print 4 }) `f` print 3 print 2
我建议避免像前一行一样缩进 `f`
:最好少缩进,这样即使对于人类来说解析也变得显而易见 reader.