Search code examples
haskelloperatorstypeclass

Haskell - custom operator for multi-parameter type class?


Suppose I have a multi-parameter type class

class MyClass a b where
    ...

foo :: MyClass a b => a -> b
foo = ...

Is it possible to define a custom infix symbol for this relation, so that I can instead write

infixr 1 ?
class a ? b where
    ...

foo :: a ? b => a -> b
foo = ...

Solution

  • Yes, with TypeOperators you can give a symbolic name to a class directly:

    {-# Language
        MultiParamTypeClasses,
        TypeOperators #-}
    
    module Example
      ( type (?)
      …
      ) where
    
    class a ? b where
      …
    
    infixr 1 ?
    
    foo :: a ? b => a -> b
    foo = …
    

    Or you can make an infix alias for a named class using ConstraintKinds:

    {-# Language
        ConstraintKinds,
        MultiParamTypeClasses,
        TypeOperators #-}
    
    module Example
      ( type (?)
      …
      ) where
    
    class C a b where
      …
    
    type a ? b = C a b
    
    infixr 1 ?
    

    Note that you may need ExplicitNamespaces for importing this as well, if it’s ambiguous.

    Another alternative is an empty subclass, if you expect to extend it with additional constraints, since this tends to be better for inference:

    class (C a b) => a ? b
    instance (C a b) => a ? b
    
    infixr 1 ?