Skip to content

Surprising interaction between quantified constraints and constraint synonyms allows for synonym instances

Summary

This looks like it shouldn't compile, but it does:

{-# LANGUAGE ConstraintKinds, KindSignatures, QuantifiedConstraints, RankNTypes
  , FlexibleContexts, MultiParamTypeClasses #-}

import Data.Kind

class SomeClass a
class OtherClass

type SomeClassUnit = OtherClass => SomeClass () :: Constraint

instance SomeClassUnit

The surprising part is AFAICT it behaves exactly as if the synonym definition was substituted into the instance declaration.

Removing the constraint in SomeClassUnit yields the expected result:

    • Illegal instance for a type synonym
      A class instance must be for a class
    • In the instance declaration for ‘SomeClassUnit’

One quirk that may or may not be relevant, if the type class in question has methods, those can't be defined in the synonym instance:

{-# LANGUAGE ConstraintKinds, KindSignatures, QuantifiedConstraints, RankNTypes
  , FlexibleContexts, MultiParamTypeClasses #-}

import Data.Kind

class SomeClass a where
  meth :: a
class OtherClass

type SomeClassUnit = OtherClass => SomeClass () :: Constraint

instance SomeClassUnit where
  meth = ()

yields

    ‘meth’ is not a (visible) method of class ‘SomeClassUnit’

However, if those methods have default implementations, AFAICT that will work as if you just declared an empty instance.

Note that it also works with parameters:

{-# LANGUAGE ConstraintKinds, KindSignatures, QuantifiedConstraints, RankNTypes
  , FlexibleContexts, MultiParamTypeClasses #-}

import Data.Kind

class SomeClass a
class OtherClass

type SomeClassSyn a = OtherClass => SomeClass a :: Constraint

instance SomeClassSyn ()

NB: instead of OtherClass any constraint will do, e.g. () ~ () or something redundant like that. However, empty constraint tuple does not trigger this.

Steps to reproduce

Try to compile the code block above.

Expected behavior

    • Illegal instance for a type synonym
      A class instance must be for a class
    • In the instance declaration for ‘SomeClassUnit’

Environment

  • GHC version used: 8.10.7, 9.0.2, 9.2.4, 9.4.2

Optional:

  • Operating System: gentoo linux
  • System Architecture: x86_64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information