# Type classes and code generation

**Keith Wansbrough
**
Keith.Wansbrough@cl.cam.ac.uk

*Tue, 17 Jun 2003 16:05:18 +0100*

>* (Moved to the Cafe)
*>*
*>* > Yes, exactly. Every class is translated to a data type declaration,
*>* > and every instance is translated to an element of that data type - a
*>* > dictionary. (Note that you can't actually write those declarations in
*>* > Haskell 98 in general, because they can have polymorphic fields; but
*>* > this is a simple extension to the language).
*>*
*>* Keith, could you elaborate on this parenthetical? Under what
*>* circumstances can you not create the dictionary datatype for a class in
*>* Haskell 98 (where the class itself is H98 :P)?
*
Sure:
>* class C a where
*>* pair :: b -> (b,a)
*>*
*>* instance C () where
*>* pair x = (x,())
*>*
*>* instance C Int where
*>* pair x = (x,42)
*>*
*>* main = do print (pair "hello" :: (String,()))
*>* print (pair "world" :: (String,Int))
*
is perfectly fine Haskell 98.
But
>* data C a = C { pair :: b -> (b,a) }
*>*
*>* dCUnit = C { pair = \ x -> (x,()) }
*>*
*>* dCInt = C { pair = \ x -> (x,42::Int) }
*>*
*>* main = do print (pair dCUnit "hello" :: (String,()))
*>* print (pair dCInt "world" :: (String,Int))
*
doesn't work:
classprob2.hs:1: Type variable not in scope: `b'
classprob2.hs:1: Type variable not in scope: `b'
You need to change the first line to this:
>* data C a = C { pair :: forall b. b -> (b,a) }
*
and then it works fine (with -fglasgow-exts). But you've now stepped
outside the bounds of Haskell 98.
This is a contrived example, but Functor and Monad from the standard
Prelude both have this property - they have universally-quantified
variables in the types of some of their methods; not all their
variables are constrained by the class constraint.
HTH.
--KW 8-)