How to define a superclass?
How do I define a superclass in Haskell? My situation is that I have defined a class StringHashed
that maps members to their names as String. I want to implement, en mass, all t
of Show t
, forcing the string name to just return Show t
. Am I correct in saying what is StringHashed
now the superclass of Show? This is what I would like to write:
class StringHashed t where
stringHash :: t -> String
instance Show t => StringHashed t where
stringHash = show
But Haskell is complaining about an invalid instance declaration. I've tried instance StringHashed (Show t)
other syntax tricks as well; nobody worked for me. I also read a suggestion on the GHC wiki which does not provide a solution. This is one . I have a usage problem -XFlexibleInstances
simply because it is not the default. Is there a suitable way to declare a generic instance? Or am I too picky about a system like Haskell?
Haskell superclasses cannot be added after the fact - they need to be mentioned in the subclass declaration. And defining an instance like you in the question, possibly with extensions, can create subtle overlap problems.
FlexibleInstances
not a problem in itself - it is one of the most innocuous extensions to GHC. The problem is that the GHC instance search method means that
instance Show t => StringHashed t where ...
defines this instance to hold for all types t
- the limitation Show t
is just an afterthought, checked after searching. This way, it will overlap with all other instances you can make, and while extension is allowed for this OverlappingInstances
, it is considered somewhat questionable to use.
However, GHC has a function DefaultSignatures
that is designed for cases similar to yours:
{-# LANGUAGE DefaultSignatures #-}
class StringHashed t where
stringHash :: t -> String
default stringHash :: Show t => t -> String
stringHash = show
instance StringHashed Int
This allows you to write a default value for a method that only works for certain types of instances. Note, however, that you still need to write the actual instance declaration for each type, but its body may be empty.