6.8.2. Flexible contexts


Allow the use of complex constraints in class declaration contexts.

In Haskell 98 the context of a class declaration (which introduces superclasses) must be simple; that is, each predicate must consist of a class applied to type variables. The extension FlexibleContexts (The context of a type signature) lifts this restriction, so that the only restriction on the context in a class declaration is that the class hierarchy must be acyclic. So these class declarations are OK:

class Functor (m k) => FiniteMap m k where

class (Monad m, Monad (t m)) => Transform t m where
  lift :: m a -> (t m) a

As in Haskell 98, the class hierarchy must be acyclic. However, the definition of “acyclic” involves only the superclass relationships. For example, this is okay:

class C a where
  op :: D b => a -> b -> b

class C a => D a where ...

Here, C is a superclass of D, but it’s OK for a class operation op of C to mention D. (It would not be OK for D to be a superclass of C.)

With the extension that adds a kind of constraints, you can write more exotic superclass definitions. The superclass cycle check is even more liberal in these cases. For example, this is OK:

class A cls c where
  meth :: cls c => c -> c

class A B c => B c where

A superclass context for a class C is allowed if, after expanding type synonyms to their right-hand-sides, and uses of classes (other than C) to their superclasses, C does not occur syntactically in the context.