Edit InfixTypeConstructors authored by Simon Peyton Jones's avatar Simon Peyton Jones
......@@ -57,10 +57,6 @@ And `type` gets an extra production:
You may say that is inconsistent, because at the value level you have to start data constructors with a ":". But the type level is already funny. The whole type-family idea (beginning with type synonyms) defines things that begin with a capital letter, but which (unlike data constructors) are not head normal forms. By the time we have full type-synonym families, they really are \*functions\* as much as any value-level function is.
Some people use constructors (think of the type a+b). Mirroring this in Haskell would make the transcription more elegantly direct.
......@@ -68,66 +64,76 @@ Some people use constructors (think of the type a+b). Mirroring this in Haskel
I can't think of any down-sides, except the slight loss of consistency ("the hobgoblin of tiny minds").
## References
## Observations
- [ Infix type constructors, classes, and type variables](http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#infix-tycons) in the GHC User's Guide.
## Tickets
- You may say that it's inconsistent for `(+)` to range over type constructors, because at the value level you have to start data constructors with a ":". But the type level is already funny. The whole type-family idea (including H98 type synonyms) defines things that begin with a capital letter, but which (unlike data constructors) are not head normal forms. Looking further ahead, by the time we have full type-synonym families, they really are *functions* as much as any value-level function is. For example it would be silly to insist on a leading colon here:
```wiki
type family (+) :: * -> * -> *
type instance Zero + n2 = n2
type instance (Succ n1) + n2 = Succ (n1 + n2)
```
- Note that classes can be infix too; this is useful.
<table><tr><th>[\#78](https://gitlab.haskell.org//haskell/prime/issues/78)</th>
<td>Add infix type constructors</td></tr></table>
## Pros
- If you say `module M( (+) ) where ...` are you exporting the type constructor `(+)` or the value `(+)`? Ditto import lists. Possibilities:
- This is a straightforward generalisation, doesn't break any existing code, and improves the consistency of the syntax.
- An ambiguous reference defaults to the locally-defined one. (If we did this we should do so consistently, including for unqualified names in the text of a module. I think this'd be a Good Thing. A warning flag could warn if you used it. It's just like shadowing.)
- If the two `(+)` things are not both locally defined, you can disambiguate with a qualified name `Prelude.(+)` or `M.(+)`. That does not help if you define *both* in `M`.
- Use a keyword to distinguish; eg `module M( data (+) ) where`. There are design issues here (e.g. distinguish `data` and `newtype`?).
## Cons
- Can you set the fixity of a type constructor `T` differently than the data constructor `T`? This is a similar ambiguity to the one in export lists. Except that in this case it is very common to have a type constructor and data constructor with the same name.
- Need to allow infix notation in contexts
- If operators are type constructors, they can't also be type variables. I know one place where people use a type variable that is an operator. Something like this.
```wiki
f :: (a >> b) => bla blah
```
- Watch out for code like this ([ http://hackage.haskell.org/trac/ghc/ticket/1727](http://hackage.haskell.org/trac/ghc/ticket/1727))
```wiki
data T (~>) = MkT (Int ~> Int)
infixr 5 `Foo`
infixr 6 `Bar`
data a `Foo` b = a `FOO` a `Bar` b
data a `Bar` b = a `BAR` b
```
## References
We'd have to use a type variable in back-quotes instead.
- [ Infix type constructors, classes, and type variables](http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#infix-tycons) in the GHC User's Guide.
## Observations
## Tickets
- Note that classes can be infix too; this is useful.
<table><tr><th>[\#78](https://gitlab.haskell.org//haskell/prime/issues/78)</th>
<td>Add infix type constructors</td></tr></table>
## Pros
- If you say `module M( (+) ) where ...` are you exporting the type constructor `(+)` or the value `(+)`? Ditto import lists. Possibilities:
- An ambiguous reference defaults to the locally-defined one. (If we did this we should do so consistently, including for unqualified names in the text of a module. I think this'd be a Good Thing. A warning flag could warn if you used it. It's just like shadowing.)
- If the two `(+)` things are not both locally defined, you can disambiguate with a qualified name `Prelude.(+)` or `M.(+)`. That does not help if you define *both* in `M`.
- Use a keyword to distinguish; eg `module M( data (+) ) where`. There are design issues here (e.g. distinguish `data` and `newtype`?).
- This is a straightforward generalisation, and doesn't break any existing code (except code that uses GHC extensions to have a type variable that is an operator).
- It's very useful to write type expressions like `(a + b)`.
- Can you set the fixity of a type constructor `T` differently than the data constructor `T`? This is a similar ambiguity to the one in export lists. Except that in this case it is very common to have a type constructor and data constructor with the same name.
## Cons
- Need to allow infix notation in contexts
- If operators are type constructors, they can't also be type variables. I know one place where people use a type variable that is an operator. Something like this.
```wiki
f :: (a :>: b) => bla blah
data T (~>) = MkT (Int ~> Int)
```
- Watch out for code like this ([ http://hackage.haskell.org/trac/ghc/ticket/1727](http://hackage.haskell.org/trac/ghc/ticket/1727))
```wiki
infixr 5 `Foo`
infixr 6 `Bar`
data a `Foo` b = a `FOO` a `Bar` b
data a `Bar` b = a `BAR` b
```
\ No newline at end of file
We'd have to use a type variable in back-quotes instead.