+ <para>
+ Type families appear in two flavours: (1) they can be defined on the
+ toplevel or (2) they can appear inside type classes (in which case they
+ are known as associated type synonyms). The former is the more general
+ variant, as it lacks the requirement for the type-indexes to coincide with
+ the class parameters. However, the latter can lead to more clearly
+ structured code and compiler warnings if some type instances were -
+ possibly accidentally - omitted. In the following, we always discuss the
+ general toplevel form first and then cover the additional constraints
+ placed on associated types.
+ </para>
+
+ <sect3 id="type-family-declarations">
+ <title>Type family declarations</title>
+
+ <para>
+ Indexed type families are introduced by a signature, such as
+<programlisting>
+type family Elem c :: *
+</programlisting>
+ The special <literal>family</literal> distinguishes family from standard
+ type declarations. The result kind annotation is optional and, as
+ usual, defaults to <literal>*</literal> if omitted. An example is
+<programlisting>
+type family Elem c
+</programlisting>
+ Parameters can also be given explicit kind signatures if needed. We
+ call the number of parameters in a type family declaration, the family's
+ arity, and all applications of a type family must be fully saturated
+ w.r.t. to that arity. This requirement is unlike ordinary type synonyms
+ and it implies that the kind of a type family is not sufficient to
+ determine a family's arity, and hence in general, also insufficient to
+ determine whether a type family application is well formed. As an
+ example, consider the following declaration:
+<programlisting>
+type family F a b :: * -> * -- F's arity is 2,
+ -- although its overall kind is * -> * -> * -> *
+</programlisting>
+ Given this declaration the following are examples of well-formed and
+ malformed types:
+<programlisting>
+F Char [Int] -- OK! Kind: * -> *
+F Char [Int] Bool -- OK! Kind: *
+F IO Bool -- WRONG: kind mismatch in the first argument
+F Bool -- WRONG: unsaturated application
+</programlisting>
+ </para>
+
+ <sect4 id="assoc-type-family-decl">
+ <title>Associated type family declarations</title>
+ <para>
+ When a type family is declared as part of a type class, we drop
+ the <literal>family</literal> special. The <literal>Elem</literal>
+ declaration takes the following form
+<programlisting>
+class Collects ce where
+ type Elem ce :: *
+ ...
+</programlisting>
+ The argument names of the type family must be class parameters. Each
+ class parameter may only be used at most once per associated type, but
+ some may be omitted and they may be in an order other than in the
+ class head. Hence, the following contrived example is admissible:
+<programlisting>
+class C a b c where
+ type T c a :: *
+</programlisting>
+ These rules are exactly as for associated data families.
+ </para>
+ </sect4>
+ </sect3>
+
+ <sect3 id="type-instance-declarations">
+ <title>Type instance declarations</title>
+ <para>
+ Instance declarations of type families are very similar to standard type
+ synonym declarations. The only two differences are that the
+ keyword <literal>type</literal> is followed
+ by <literal>instance</literal> and that some or all of the type
+ arguments can be non-variable types, but may not contain forall types or
+ type synonym families. However, data families are generally allowed, and
+ type synonyms are allowed as long as they are fully applied and expand
+ to a type that is admissible - these are the exact same requirements as
+ for data instances. For example, the <literal>[e]</literal> instance
+ for <literal>Elem</literal> is
+<programlisting>
+type instance Elem [e] = e
+</programlisting>
+ </para>
+ <para>
+ Type family instance declarations are only legitimate when an
+ appropriate family declaration is in scope - just like class instances
+ require the class declaration to be visible. Moreover, each instance
+ declaration has to conform to the kind determined by its family
+ declaration, and the number of type parameters in an instance
+ declaration must match the number of type parameters in the family
+ declaration. Finally, the right-hand side of a type instance must be a
+ monotype (i.e., it may not include foralls) and after the expansion of
+ all saturated vanilla type synonyms, no synonyms, except family synonyms
+ may remain. Here are some examples of admissible and illegal type
+ instances:
+<programlisting>
+type family F a :: *
+type instance F [Int] = Int -- OK!
+type instance F String = Char -- OK!
+type instance F (F a) = a -- WRONG: type parameter mentions a type family
+type instance F (forall a. (a, b)) = b -- WRONG: a forall type appears in a type parameter
+type instance F Float = forall a.a -- WRONG: right-hand side may not be a forall type
+
+type family G a b :: * -> *
+type instance G Int = (,) -- WRONG: must be two type parameters
+type instance G Int Char Float = Double -- WRONG: must be two type parameters
+</programlisting>
+ </para>