|
|
# Proposal: [QualifiedOperators](qualified-operators)
|
|
# Proposal: Change the syntax of qualified operators
|
|
|
|
|
|
|
|
<table><tr><th> Ticket </th>
|
|
|
|
|
<th>[\#127](https://gitlab.haskell.org//haskell/prime/issues/127)</th></tr>
|
|
|
|
|
<tr><th> Dependencies </th>
|
|
|
|
|
<th></th></tr>
|
|
|
|
|
<tr><th> Related </th>
|
|
|
|
|
<th> replaces [QualifiedIdentifiers](qualified-identifiers) and [CompositionAsDot](composition-as-dot)</th></tr></table>
|
|
|
|
|
|
|
|
|
|
## Compiler support
|
|
|
|
|
|
|
|
|
|
<table><tr><th> GHC </th>
|
|
|
|
|
<th> full (`-XNewQualifiedOperators`)
|
|
|
|
|
</th></tr>
|
|
|
|
|
<tr><th> nhc98 </th>
|
|
|
|
|
<th> none
|
|
|
|
|
</th></tr>
|
|
|
|
|
<tr><th> Hugs </th>
|
|
|
|
|
<th> none
|
|
|
|
|
</th></tr>
|
|
|
|
|
<tr><th> UHC </th>
|
|
|
|
|
<th> none
|
|
|
|
|
</th></tr>
|
|
|
|
|
<tr><th> JHC </th>
|
|
|
|
|
<th> none
|
|
|
|
|
</th></tr>
|
|
|
|
|
<tr><th> LHC </th>
|
|
|
|
|
<th> none
|
|
|
|
|
</th></tr></table>
|
|
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Change the syntax for qualified operators from `Prelude.>>=` to `Prelude.(>>=)`.
|
|
|
|
|
|
|
|
|
|
## Description
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The problem is that right now, qualified operators are written like
|
|
The problem is that right now, qualified operators are written like
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
```wiki
|
|
|
Prelude.>>=
|
|
Prelude.>>=
|
|
|
```
|
|
```
|
| ... | @@ -45,6 +12,7 @@ The problem is that right now, qualified operators are written like |
... | @@ -45,6 +12,7 @@ The problem is that right now, qualified operators are written like |
|
|
|
|
|
|
|
but the difficulty with this is that we now have lexemes like `Prelude..` (qualified '.'), which means for example that
|
|
but the difficulty with this is that we now have lexemes like `Prelude..` (qualified '.'), which means for example that
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
```wiki
|
|
|
[Red..]
|
|
[Red..]
|
|
|
```
|
|
```
|
| ... | @@ -53,8 +21,10 @@ but the difficulty with this is that we now have lexemes like `Prelude..` (quali |
... | @@ -53,8 +21,10 @@ but the difficulty with this is that we now have lexemes like `Prelude..` (quali |
|
|
doesn't parse as you might expect: `Red..` is a qualified operator.
|
|
doesn't parse as you might expect: `Red..` is a qualified operator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The proposal is as follows. Qualified operators are written
|
|
The proposal is as follows. Qualified operators are written
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
```wiki
|
|
|
Prelude.(>>=)
|
|
Prelude.(>>=)
|
|
|
```
|
|
```
|
| ... | @@ -62,8 +32,11 @@ The proposal is as follows. Qualified operators are written |
... | @@ -62,8 +32,11 @@ The proposal is as follows. Qualified operators are written |
|
|
|
|
|
|
|
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.
|
|
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
|
|
`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
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
```wiki
|
|
|
var -> varid | ( varsym )
|
|
var -> varid | ( varsym )
|
|
|
qvar -> [ modid . ] var
|
|
qvar -> [ modid . ] var
|
| ... | @@ -76,8 +49,10 @@ and are **prefix**; that is, the above is a qualified version of `(>>=)`. One ob |
... | @@ -76,8 +49,10 @@ and are **prefix**; that is, the above is a qualified version of `(>>=)`. One ob |
|
|
(with identical rules for constructors). This grammar has slightly fewer productions than Haskell 98.
|
|
(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
|
|
Note that this grammar is nested differently than in Haskell 98: the layering is
|
|
|
|
|
|
|
|
|
|
|
|
- varid: plain variables
|
|
- varid: plain variables
|
|
|
- var: adds parenthesised operators
|
|
- var: adds parenthesised operators
|
|
|
- qvar: adds qualification
|
|
- qvar: adds qualification
|
| ... | @@ -86,6 +61,7 @@ Note that this grammar is nested differently than in Haskell 98: the layering is |
... | @@ -86,6 +61,7 @@ Note that this grammar is nested differently than in Haskell 98: the layering is |
|
|
|
|
|
|
|
So, an infix qualified operator is written
|
|
So, an infix qualified operator is written
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
```wiki
|
|
|
`Prelude.(>>=)`
|
|
`Prelude.(>>=)`
|
|
|
```
|
|
```
|
| ... | @@ -94,65 +70,11 @@ So, an infix qualified operator is written |
... | @@ -94,65 +70,11 @@ So, an infix qualified operator is written |
|
|
for consistency we also allow ``(>>=)``. The fixity of these would be the same as the fixity of `>>=`.
|
|
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](qualified-identifiers)). 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:
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
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.
|
|
|
left section right section prefix
|
|
|
|
|
unqualified (+ 1) (1 +) (+)
|
|
|
|
|
Haskell 98 (M.+ 1) (1 M.+) (M.+)
|
|
|
|
|
proposed (`M.(+)` 1) (1 `M.(+)`) M.(+)
|
|
|
|
|
or(*) (flip M.(+) 1) (M.(+) 1)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(\*) only if precedence isn't important, e.g. not in cases like ``M.(+)` x `M.(*)` y`.
|
|
|
|
|
|
|
|
|
|
## Report Delta
|
|
|
|
|
|
|
|
|
|
### Section 2.4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Add
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
|
var -> varid | ( varsym )
|
|
|
|
|
con -> conid | ( consym )
|
|
|
|
|
|
|
|
|
|
qvar -> [ modid . ] var
|
|
|
|
|
qcon -> [ modid . ] con
|
|
|
|
|
|
|
|
|
|
varop -> varsym | `var`
|
|
|
|
|
qvarop -> varsym | `qvar`
|
|
|
|
|
conop -> consym | `con`
|
|
|
|
|
qconop -> consym | `qcon`
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remove `qvarid`, `qvarsym`, `qconid`, `qvarsym` from the description of qualified identifiers. Add text to explain the syntax of qualified operators (moving some of it from 3.2 and updating to the new syntax), and modify the text describing qualified identifiers. Adjust the table of "Sample lexical analyses" according to the new syntax.
|
|
|
|
|
|
|
|
|
|
`tyvar`, `tycon`, `tycls`, `qtycon`, `qtycls`, remain as they are.
|
|
|
|
|
|
|
|
|
|
### Section 3.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Remove `var`, `con`, `qvar`, `qcon`, `varop`, `qwvarop`, `conop`, `qconop` and associated text (some of which moved to 2.4)
|
|
|
|
|
|
|
|
|
|
### Section 9 (Syntax reference)
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
Make corresponding changes as for 2.4 and 3.2 above. |
|
|