Note [Injectivity annotation]
A user can declare a type family to be injective:
type family Id a = r | r -> a where ...
* The part after the "|" is called "injectivity annotation".
* "r -> a" part is called "injectivity condition"; at the moment terms
"injectivity annotation" and "injectivity condition" are synonymous
because we only allow a single injectivity condition.
* "r" is the "LHS of injectivity condition". LHS can only contain the
variable naming the result of a type family.
* "a" is the "RHS of injectivity condition". RHS contains space-separated
type and kind variables representing the arguments of a type
family. Variables can be omitted if a type family is not injective in
these arguments. Example:
type family Foo a b c = d | d -> a c where ...
Note that:
(a) naming of type family result is required to provide injectivity
annotation
(b) for associated types if the result was named then injectivity annotation
is mandatory. Otherwise result type variable is indistinguishable from
associated type default.
It is possible that in the future this syntax will be extended to support
more complicated injectivity annotations. For example we could declare that
if we know the result of Plus and one of its arguments we can determine the
other argument:
type family Plus a b = (r :: Nat) | r a -> b, r b -> a where ...
Here injectivity annotation would consist of two comma-separated injectivity
conditions.
See also Note [Injective type families] in GHC.Core.TyCon References 0
This Note does not link to any other.
Referenced by 4
- Language.Haskell.Syntax.Decls call site ×2
- Verifying injectivity annotation GHC.Core.FamInstEnv
- Renaming injectivity annotation GHC.Rename.Module