Operator on do indentation

耗尽温柔 提交于 2019-12-10 18:24:28

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!