summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2014-07-15 07:43:55 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2014-07-15 07:43:55 +0100
commit9b8ba62991ae22420a0c4486127a3b22ee7f22bd (patch)
tree69e03640c54a4393efe91a5f184b764692460808 /docs
parentf692e8e7cde712cc4dce4245d5745063fd8b0626 (diff)
downloadhaskell-9b8ba62991ae22420a0c4486127a3b22ee7f22bd.tar.gz
Entirely re-jig the handling of default type-family instances (fixes Trac #9063)
In looking at Trac #9063 I decided to re-design the default instances for associated type synonyms. Previously it was all jolly complicated, to support generality that no one wanted, and was arguably undesirable. Specifically * The default instance for an associated type can have only type variables on the LHS. (Not type patterns.) * There can be at most one default instances declaration for each associated type. To achieve this I had to do a surprisingly large amount of refactoring of HsSyn, specifically to parameterise HsDecls.TyFamEqn over the type of the LHS patterns. That change in HsDecls has a (trivial) knock-on effect in Haddock, so this commit does a submodule update too. The net result is good though. The code is simpler; the language specification is simpler. Happy days. Trac #9263 and #9264 are thereby fixed as well.
Diffstat (limited to 'docs')
-rw-r--r--docs/users_guide/glasgow_exts.xml103
1 files changed, 72 insertions, 31 deletions
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index f1d7b94224..42e04fc68c 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -6024,28 +6024,39 @@ instance (GMapKey a, GMapKey b) => GMapKey (Either a b) where
data GMap (Either a b) v = GMapEither (GMap a v) (GMap b v)
...
-instance (Eq (Elem [e])) => Collects ([e]) where
+instance Eq (Elem [e]) => Collects [e] where
type Elem [e] = e
...
</programlisting>
- The most important point about associated family instances is that the
- type indexes corresponding to class parameters must be identical to
- the type given in the instance head; here this is the first argument
- of <literal>GMap</literal>, namely <literal>Either a b</literal>,
- which coincides with the only class parameter.
- </para>
- <para>
- Instances for an associated family can only appear as part of
- instance declarations of the class in which the family was declared -
- just as with the equations of the methods of a class. Also in
- correspondence to how methods are handled, declarations of associated
- types can be omitted in class instances. If an associated family
- instance is omitted, the corresponding instance type is not inhabited;
+Note the following points:
+<itemizedlist>
+<listitem><para>
+ The type indexes corresponding to class parameters must have precisely the same shape
+ the type given in the instance head. To have the same "shape" means that
+ the two types are identical modulo renaming of type variables. For example:
+<programlisting>
+instance Eq (Elem [e]) => Collects [e] where
+ -- Choose one of the following alternatives:
+ type Elem [e] = e -- OK
+ type Elem [x] = x -- OK
+ type Elem x = x -- BAD; shape of 'x' is different to '[e]'
+ type Elem [Maybe x] = x -- BAD: shape of '[Maybe x]' is different to '[e]'
+</programlisting>
+</para></listitem>
+<listitem><para>
+ An instances for an associated family can only appear as part of
+ an instance declarations of the class in which the family was declared,
+ just as with the equations of the methods of a class.
+</para></listitem>
+<listitem><para>
+ The instance for an associated type can be omitted in class instances. In that case,
+ unless there is a default instance (see <xref linkend="assoc-decl-defs"/>),
+ the corresponding instance type is not inhabited;
i.e., only diverging expressions, such
as <literal>undefined</literal>, can assume the type.
- </para>
- <para>
- Although it is unusual, there can be <emphasis>multiple</emphasis>
+</para></listitem>
+<listitem><para>
+ Although it is unusual, there (currently) can be <emphasis>multiple</emphasis>
instances for an associated family in a single instance declaration.
For example, this is legitimate:
<programlisting>
@@ -6059,8 +6070,10 @@ instance GMapKey Flob where
Since you cannot give any <emphasis>subsequent</emphasis> instances for
<literal>(GMap Flob ...)</literal>, this facility is most useful when
the free indexed parameter is of a kind with a finite number of alternatives
- (unlike <literal>*</literal>).
- </para>
+ (unlike <literal>*</literal>). WARNING: this facility may be withdrawn in the future.
+</para></listitem>
+</itemizedlist>
+</para>
</sect3>
<sect3 id="assoc-decl-defs">
@@ -6078,22 +6091,50 @@ class IsBoolMap v where
instance IsBoolMap [(Int, Bool)] where
lookupKey = lookup
</programlisting>
-The <literal>instance</literal> keyword is optional.
- </para>
+In an <literal>instance</literal> declaration for the class, if no explicit
+<literal>type instance</literal> declaration is given for the associated type, the default declaration
+is used instead, just as with default class methods.
+</para>
<para>
-There can also be multiple defaults for a single type, as long as they do not
-overlap:
+Note the following points:
+<itemizedlist>
+<listitem><para>
+ The <literal>instance</literal> keyword is optional.
+</para></listitem>
+<listitem><para>
+ There can be at most one default declaration for an associated type synonym.
+</para></listitem>
+<listitem><para>
+ A default declaration is not permitted for an associated
+ <emphasis>data</emphasis> type.
+</para></listitem>
+<listitem><para>
+ The default declaration must mention only type <emphasis>variables</emphasis> on the left hand side,
+ and the right hand side must mention only type varaibels bound on the left hand side.
+ However, unlike the associated type family declaration itself,
+ the type variables of the default instance are independent of those of the parent class.
+</para></listitem>
+</itemizedlist>
+Here are some examples:
<programlisting>
-class C a where
- type F a b
- type F a Int = Bool
- type F a Bool = Int
+ class C a where
+ type F1 a :: *
+ type instance F1 a = [a] -- OK
+ type instance F1 a = a->a -- BAD; only one default instance is allowed
+
+ type F2 b a -- OK; note the family has more type
+ -- variables than the class
+ type instance F2 c d = c->d -- OK; you don't have to use 'a' in the type instance
+
+ type F3 a
+ type F3 [b] = b -- BAD; only type variables allowed on the LHS
+
+ type F4 a
+ type F4 b = a -- BAD; 'a' is not in scope in the RHS
</programlisting>
+</para>
-A default declaration is not permitted for an associated
-<emphasis>data</emphasis> type.
- </para>
- </sect3>
+</sect3>
<sect3 id="scoping-class-params">
<title>Scoping of class parameters</title>