问题
hindent
changed my code to:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
I can't determine if the finally
applies to the rest of the do
block, or just the state beginning onException
. According to this,
If you see something unexpected in a list, like where, insert a closing brace before instead of a semicolon.
I'm unsure if that rule is applying here.
Does the `finally`
apply to the rest of the do, or just the last statement and why?
回答1:
We can find out using GHCi: writing
Prelude> let f = (>>)
Prelude> :{
Prelude| do print 5
Prelude| print 4
Prelude| `f` print 3
Prelude| print 2
Prelude| :}
causes the following type error (not a parse error!)
<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
Looking at the list lines, we discover how GHCi parsed the code, which is printed with explicit braces-and-semicolons.
There, we see that the `f`
part closed the do
block! This makes the whole do
block to be the first argument to f
. Further, the next lines, no longer being in a block, now form a single expression print 4 print 2
which is used as the second argument for f
. This triggers a type error since it calls print
with three arguments.
Indeed, the brace }
was inserted before `f`
because of the rule mentioned by the OP: when something does not parse in a block, we add }
and continue.
Summarizing, if `f`
is indented more, the block is parsed as
do print 5
print 4 `f` print 3
print 2
If `f`
is indented as the previous line, or less, the block is parsed as
(do { print 5
; print 4 }) `f` print 3 print 2
I would suggest to avoid indenting `f`
exactly as the previous line: it is better to indent it less, so that the parsing becomes obvious even to a human reader.
回答2:
The following does not actually adress the code you posted, but the question you seemed to be asking. It adresses the following code instead:
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
░`finally` removeFileIfExists inputFile
chi's answer adresses the actually posted code, with `finally`
not indented any further than download
and onException
. I'd remark that this is bad style: when writing that, be sure to indent it less, i.e.
do download i inputFile
onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name)
`finally` removeFileIfExists inputFile
As Willem Van Onsem commented, function applications always take precedence before infix applications. This is true for both “true infix operators” like +
or >>=
, and for backtick-infixes... if fact there is no baked in distinction between these sorts of operators as far as precedence is concerned: for all infixes the precedence is determined by a fixity declaration, such as
infixl 6 +
infix 4 `elem`
The fixity is a number in the range 0..9, and fixity can be either left- right- or non-associative. If no fixity is declared (as with most named functions, whereas for symbol-infixes it's highly recommended to give a fixity declaration), the default infixl 9
is used, i.e. basically the highest legal fixity you could manually assign.
OTOH, function application is always infixl 10
as it were, i.e. it binds tigher than any infix, no matter how it's declared. So, your example is parsed as
do (download i inputFile)
( (onException
(callProcess (List.head args) (List.tail args))
(removeFileIfExists name))
`finally`
(removeFileIfExists inputFile) )
来源:https://stackoverflow.com/questions/48984756/operator-on-do-indentation