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.
finally (onException (callProcess ...) (removeFileIfExists name)) (removeFileIfExists inputFile)
.finally
is thus the main function. – Turoff