Reputation: 395
How does one define a super class in Haskell? My situation is that I have defined a class StringHashed
that maps members to their names as a String. I wish to implement, en mass, all t
from Show t
by making the string name simply return show t
. Am I right in saying that StringHashed
is now a superclass of Show? Here is what I would like to be able to write:
class StringHashed t where
stringHash :: t -> String
instance Show t => StringHashed t where
stringHash = show
But Haskell complains about an invalid instance declaration. I have also tried instance StringHashed (Show t)
and other syntactical dribble; none have worked for me. I have also read a proposal on the GHC wiki that provides no solution. This is the one. I have concern about using -XFlexibleInstances
simply because it is not default. Is there a proper way to achieve a general instance declaration? Or am I being too demanding of Haskell's type system?
Upvotes: 4
Views: 653
Reputation: 18189
Haskell superclasses cannot be added after the fact - they need to be mentioned in the subclass's declaration. And defining an instance like you do in the question, while possible with extensions, can create subtle overlap problems.
FlexibleInstances
itself is not the problem - it's one of GHC's most innocuous extensions. The problem is that GHC's instance lookup method means that
instance Show t => StringHashed t where ...
defines this instance to hold for all types t
- the Show t
restriction is only an afterthought checked after lookup. So it will overlap with all other instances you can make, and while there is an extension OverlappingInstances
to allow this, it is considered somewhat dubious to use.
However GHC has a feature DefaultSignatures
, which is designed for use 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 for the method which only works for some instance types. Note however, that you still need to write an actual instance declaration for each type - but its body can be empty.
Upvotes: 11