| Version 6 (modified by simonmar@…, 4 years ago) |
|---|
Proposal: QualifiedOperators
| Ticket | #127 |
| Dependencies | |
| Related | replaces QualifiedIdentifiers and CompositionAsDot |
Compiler support
| GHC | full (-XNewQualifiedOperators) |
| nhc98 | none |
| Hugs | none |
| UHC | none |
| JHC | none |
| LHC | none |
Summary
Change the syntax for qualified operators from Prelude.>>= to Prelude.(>>=).
Description
The problem is that right now, qualified operators are written like
Prelude.>>=
but the difficulty with this is that we now have lexemes like Prelude.. (qualified '.'), which means for example that
[Red..]
doesn't parse as you might expect: Red.. is a qualified operator.
The proposal is as follows. Qualified operators are written
Prelude.(>>=)
and are prefix; that is, the above is a qualified version of (>>=). One obvious advantage is that this is much easier to read: the dot is clearly separated from the operator being qualified.
Prelude.(>>=) has to be a single lexeme, because there's no way to lift the syntax of qualified names into the context-free grammar. So this forces us to move the syntax for parenthesized operators and `..` down to the lexical syntax (back where it was in Haskell 1.2?). But that's not too bad; one possibility for the lexical grammar is
var -> varid | ( varsym ) qvar -> [ modid . ] var varop -> varsym | `var` qvarop -> varsym | `qvar`
(with identical rules for constructors). This grammar has slightly fewer productions than Haskell 98.
Note that this grammar is nested differently than in Haskell 98: the layering is
- varid: plain variables
- var: adds parenthesised operators
- qvar: adds qualification
- qvarop: adds ..
So, an infix qualified operator is written
`Prelude.(>>=)`
for consistency we also allow `(>>=)`. The fixity of these would be the same as the fixity of >>=.
You might argue that it is inconsistent to allow `(+)` but not allow (`plus`), but the justification is simply that (..) and `..` are not dual in this design.
This proposal simplifies the story for composition: we don't have to worry about whether you need a space after Prelude... Also, Prelude.(.) is much easier to read. The only disadvantage I can see is that it could break some code, but probably very little.
Summary: pros
- Eliminates odd cases in the lexical syntax: M.., M..., M.... are 1, 2, and 3 lexemes respectively in Haskell 98 (see also QualifiedIdentifiers). This can be confusing, e.g. [Monday..].
- A simple rule: if a lexeme begins with a letter, it is not an infix operator. Infix operators begin with a symbol character or `.
Summary: cons
- The syntax for infix qualified operators is heavier: `Prelude.(>>=)` vs. Prelude.>>=
- Using the workaround let (>>=) = Prelude.(>>=) in ... does not work, because >>= has the default fixity.
- `...` and (...) are not dual
- we lose some consistency with sections, which become quite unwieldy with the new syntax:
left section right section prefix unqualified (+ 1) (1 +) (+) Haskell 98 (M.+ 1) (1 M.+) (M.+) proposed (`M.(+)` 1) (1 `M.(+)`) M.(+) or(*) (M.(+) 1) (flip M.(+) 1)
(*) only if precedence isn't important, e.g. not in cases like `M.(+)` x `M.(*)` y.
