[Haskell-cafe] Issues(Bugs?) with GHC Type Families

Ryan Ingram ryani.spam at gmail.com
Thu Mar 6 21:52:26 EST 2008


2008/3/6 Hugo Pacheco <hpacheco at gmail.com>:
> How could I compile such an example, assuming that I want to use the
> instance C String for Strings only and the more general instance for the
> rest?

> class C a where
>     c :: a
> instance C Char where
>     c = 'a'
> instance C a => C [a] where
>     c = [c :: a,c :: a]
> instance C String where
>     c = "a"
> cc = c :: String

This is actually a general issue with the way typeclasses are defined
in Haskell; the accepted solution is what the "Show" typeclass does:

> class C a where
>    c :: a
>    cList :: [a]
>    cList = [c,c]

> instance C Char where
>    c = 'a'
>    cList = "a" -- replaces instance for String above
> instance C a => C [a] where
>    c = cList
> cc = c :: String

I don't really like this solution; it feels like a hack and it relies
on knowing when you define the typeclass what sort of overlap you
expect.

I wish there was some form of instance declaration that let you do
case analysis; something similar to the following:

instances C [a] where
    instance C String where
        c = "a"
    instance C a => C [a] where
        c = [c,c]
    instance Num a => C [a] where
        c = [0]

When trying to find a constraint for C [a] for some type a, the
instances would be checked in order:
1) If a was Char, the first instance would be selected.
2) Otherwise, if there was an instance for C a, the second instance
would be selected.
3) Otherwise, if there was an instance for Num a, the third instance
would be selected.
4) Otherwise a type error would occur.

Then overlapping instances wouldn't be required nearly as often; the
relevant instances would all have to be defined in one place, but
that's often the case anyways.  In exchange for giving up some of the
openness of typeclasses, you would get the benefit of being able to
have better control over instance definitions.

You could also use this to create "closed" typeclasses using
"instances C a where ..."; the compiler would then know that all
possible instances were defined at that location; any other definition
would clearly overlap and so the compiler could rule out their
existence immediately.  There might be some benefit in this case in
terms of removing ambiguities that currently arise due to open
typeclasses.

  -- ryan


More information about the Haskell-Cafe mailing list