<P><FONT SIZE=2>Thanks Wren, that makes sense.<BR>
<BR>
Ryan Ingram wrote:<BR>
&gt; Think of classes like data declarations; an instance with no context<BR>
&gt; is a constant, and one with context is a function.&nbsp; Here's a simple<BR>
&gt; translation of your code into data; this is very similar to the<BR>
&gt; implementation used by GHC for typeclasses:<BR>
&gt;<BR>
&gt; &gt; data EqDict a = EqDict { eq :: a -&gt; a -&gt; Bool }<BR>
&gt; &gt; data ShowDict a = ShowDict { show :: a -&gt; String }<BR>
&gt; &gt; data NumDict a = NumDict { num_eq :: EqDict a, num_show :: ShowDict a, plus :: a -&gt; a -&gt; a }<BR>
&gt;<BR>
&gt; The goal of the compiler is to turn your instance declarations into<BR>
&gt; these structures automatically.<BR>
<BR>
Another way of explaining this, if you're a Curry--Howard fan, is that<BR>
the compiler is looking for a proof that the type belongs to the class,<BR>
where =&gt; is logical implication. This is very similar to how Prolog<BR>
searches for proofs, if you're familiar with logic programming.<BR>
<BR>
Classes declare the existence of logical predicates, along with the form<BR>
of what a &quot;proof&quot; of the predicate looks like. Instances declare a<BR>
particular proof (or family of proofs if there are free type variables).<BR>
<BR>
<BR>
Thus, the Num class is declared as,<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp; class (Eq a, Show a) =&gt; Num a where ...<BR>
<BR>
which says: for any type |a|, we can prove |Num a| if (and only if) we<BR>
can prove |Eq a| and |Show a|, and can provide definitions for all the<BR>
functions in the class using only the assumptions that |Eq a|, |Show a|,<BR>
and |Num a|.<BR>
<BR>
<BR>
When you declare,<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp; instance Eq b =&gt; Eq (Foo b) where ...<BR>
<BR>
you're providing a proof of |Eq b =&gt; Eq (Foo b)|. That is, you can<BR>
provide a conditional proof of |Eq (Foo b)|, given the assumption that<BR>
you have a proof of |Eq b|.<BR>
<BR>
Notice how the context for instances is subtly different from the<BR>
context for classes. For instances you're saying that this particular<BR>
proof happens to make certain assumptions; for classes you're saying<BR>
that all proofs require these assumptions are valid (that is, providing<BR>
the functions isn't enough to prove membership in the class).<BR>
<BR>
<BR>
Later on you declare,<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp; instance Num (Foo b) where ...<BR>
<BR>
but remember that this proof must have the same form as is declared by<BR>
the class definition. This means that you must have proofs of |Eq (Foo<BR>
b)| and |Show (Foo b)|. Unfortunately, you don't actually have a proof<BR>
of |Eq (Foo b)|, you only have a proof of |Eq b =&gt; Eq (Foo b)|. In order<BR>
to use that proof you must add the |Eq b| assumption to this proof as well:<BR>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp; instance Eq b =&gt; Num (Foo b) where ...<BR>
<BR>
When the compiler is complaining about the original one, what it's<BR>
telling you is that the |Num (Foo b)| proof can never exist because you<BR>
can never provide it with a proof of |Eq (Foo b)| in order to fulfill<BR>
its requirements.<BR>
<BR>
--<BR>
Live well,<BR>
~wren</FONT>
</P>