
2008/3/6 Hugo Pacheco
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