In the previous version of Ormolu, operator chains weren’t represented by a sequence of operands interleaved with infix operators, but rather as a binary tree data OpTree = OpNode | OpBranch OpTree Operator OpTree, directly extracted from the AST returned by ghc-lib-parser.Īt this point, it is crucial to remember that Haskell allows its users to define custom infix operators, in any module. But then, what should we do to produce the most readable and least surprising output? As soon as one line break is introduced in an operator chain by the programmer, Ormolu is allowed to reformat the chain in a multi-line fashion, as long as the AST remains the same. Formatting issues with the previous version of OrmoluĪccording to Ormolu’s core principles, any single-line expression should stay single-line, and as a result, Ormolu doesn’t need to do much work for a single-line operator chain, except from checking that spaces are effectively put around each infix operator.įor multi-line operator chains, however, it’s a completely different story. Fortunately, that particular combination is uncommon in practice. Likewise, two operators with the same precedence level, but with different associativity directions cannot be chained together without explicit parentheses. = is non-associative, which is a sensible choice given its signature Ord a => a -> a -> Bool: 1 /= 2 /= 3 would make no sense). On the other hand, the mathematical exponentiation, ^, is right associative: 2^3^3 means 2^(3^3).Ī non-associative operator cannot be chained with operators of the same precedence level, and often indicates that the operator has a different return type than those of its left and right operands (e.g. However, all of these four operators are left associative, which means that, in a chain of + and -, or in a chain of * and /, the operations should be computed left-to-right: 1 + 2 - 3 - 4 = ((1 + 2) - 3) - 4. The associativity direction is different from the mathematical definition of associativity: + and * are associative in the mathematical sense (because (a + b) + c = a + (b + c) and (a * b) * c = a * (b * c)), whereas - and / are not. In order to do so, we need to look at the associativity direction of each operator. 1 + 2 - 3 - 4), no operator has higher priority than the other, but we still need to order the computations. When several operators in a chain share the same precedence level (e.g. An associativity direction: an infix operator can be either left associative ( infixl), right associative ( infixr), or non-associative ( infix) and indicates, in the absence of parentheses, in which order should the computations be made inside a group of operators having the same precedence level.* has precedence level 7, whereas + has precedence level 6 in Haskell). An infix operator with a higher precedence level will bind more tightly than an operator with a lower precedence level (e.g. A precedence, which can be seen as a priority level.From now on, I will call such a sequence of operands interleaved with infix operators an operator chain. Indeed, it’s really neat to write 1 + 2 * 5 * 6 instead of 1 + ((2 * 5) * 6), which would be required without such rules. Moreover, most of the time, these operators can be “chained” together without parentheses, and in that case, fixity rules determine the meaning of an expression. Operator chainsĪlmost all programming languages allow the use of infix operators, especially for the four basic numeric operators, +, -, * and /. In turn, this blog post will be focusing on the challenge of formatting infix operator chains in Haskell, which is notoriously difficult and has been my primary goal for the last two months. It makes use of the parser of GHC itself, so as to prevent parsing issues that unfortunately some other Haskell formatters have.Īlexander Esgen detailed several improvements he made to Ormolu during his internship in a previous blog post. The Ormolu project, led by Mark Karpov at Tweag, has been providing a reliable way to format Haskell source files for a few years now.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |