Indent operator

hindent changed my code to:

 do download i inputFile onException (callProcess (List.head args) (List.tail args)) (removeFileIfExists name) `finally` removeFileIfExists inputFile 

I cannot determine if finally refers to the rest of the do block or just to the start of the onException state. According to this ,

If you see something unexpected in the list, for example, where, insert closing the bracket before the semicolon.

I am not sure if this rule applies here.

Is `finally` for the rest of do, or just for the last statement, and why?

+3
source share
2 answers

We can find out using GHCi: record

 Prelude> let f = (>>) Prelude> :{ Prelude| do print 5 Prelude| print 4 Prelude| `f` print 3 Prelude| print 2 Prelude| :} 

causes the following type error (and not a parsing 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 

By looking at the lines of the list, we learn how GHCi parsed code that prints with explicit brackets and a semicolon.

There we see that the `f` part closed the do block! This makes the entire do block the first argument to f . Further, the following lines, which are no longer in the block, now form one print 4 print 2 expression, which is used as the second argument to f . This causes a type error because it causes print with three arguments.

Indeed, a bracket } was inserted before `f` because of the rule mentioned by OP: when something is not parsed in a block, we add } and continue.

To summarize, if `f` 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 avoiding the indentation of `f` exactly the same way as the previous line: it is better to indent less, so that parsing becomes obvious even to the reader.

+4
source

Actually, you should not indicate the code that you sent, but the question that you seemed to ask . Instead, it refers to the following code:

 do download i inputFile onException (callProcess (List.head args) (List.tail args)) (removeFileIfExists name) โ–‘`finally` removeFileIfExists inputFile 

chi answer addresses the actually published code, `finally` has no indentation except download and onException . I would notice that this is a bad style: when you write this, be sure to release 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, functional applications always take precedence over infix applications. This is true both for "real infix operators", such as + or >>= , and for reverse drifts ... if there is no fact that there is no difference between these types of operators with respect to priority: for all infix, priority is determined by a commit declaration, eg

 infixl 6 + infix 4 `elem` 

A commit is a number in the range of 0..9, and a commit can be either left, right, or non-associative. If a non-commit is declared (as is the case for most named functions, while for infix characters it is strongly recommended to declare a commit), the default value is infixl 9 , i.e. basically the highest legal commit you could manually assign.

OTOH, application application always infixl 10 as it were, i.e. it binds a tiger than any infix, no matter how it is declared. So your example is parsed as

 do (download i inputFile) ( (onException (callProcess (List.head args) (List.tail args)) (removeFileIfExists name)) `finally` (removeFileIfExists inputFile) ) 
0
source

Source: https://habr.com/ru/post/1275683/


All Articles