Version 3 (modified by Simon Peyton Jones, 9 years ago) (diff)

Infix Type Constructors

Brief Explanation

GHC allows type constructors to be infix operators (conops, beginning with :, but not including : itself).

Changes to the syntax may depend on whether CompositionAsDot is adopted, but roughly speaking we add

 qtycon   -> qconid  | ( qconsym )
 qtyconop -> qconsym | ` qconid `

And type gets an extra production:

 type    -> btype qtyconop type

(modulo FixityResolution). Also, there are obvious changes to the grammar for type, data, and newtype declarations.

Secondly, I propose to allow varsyms to be used as type constructors. For example, currently "+" is a varsym, so at the type level it'd behave like a type variable

        data T (+) = MkT (Int + Int)

It's not impossible that this might be useful, although the binding site looks clumsy. But it misses a much more useful opportunity. What we want is to say

        data a + b = Left a | Right b

That is, we want to define the type constructor (+). Currently we have to use the clumsy :+ notation:

        data a :+ b = Left a | Right b

Yuk. So I propose that varsyms can be used as type constructors, and not as type variables.

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 Haskell as a laboratory in which to write their cunning type ideas. In mathematics, operators are invariably top-level type constructors (think of the type a+b). Mirroring this in Haskell would make the transcription more elegantly direct.

I can't think of any down-sides, except the slight loss of consistency ("the hobgoblin of tiny minds").



Add infix type constructors


  • This is a straightforward generalisation, doesn't break any existing code, and improves the consistency of the syntax.



  • Note that classes can be infix too; this is useful.
  • Need to have a way to set the fixity of a type constructor T differently than the data constructor T (or not?).
  • Need to allow infix notation in contexts
    f :: (a :>: b) => bla blah
  • Watch out for code like this (
     infixr 5 `Foo`
     infixr 6 `Bar`
     data a `Foo` b = a `FOO` a `Bar` b
     data a `Bar` b = a `BAR` b