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-)