In the following example:
data ColourName
= White
| Grey
| Gray
| Black
| Blue
-- ...
-- hundreds more of colours
-- ...
| LastColor
deriving (Read, Show, Eq)
I'd like to redefine (==)
so that Grey
and Gray
evaluate as equal.
Obviously, one way would be to not include Eq
in deriving
, however, then I'd have to define
(==) :: ColourName
(==) White White = True
(==) Gray Gray = True
(==) Grey Grey = True
(==) Gray Grey = True
(==) Grey Gray = True
(==) Black Black = True
-- frickin' log of other colors, hundreds of lines of typing
(==) LastColor LastColor = True
(==) a b = False
which is nothing I plan to do.
I also can't do
instance Eq ColourName where
(==) :: ColourName -> ColourName -> Bool
(==) Gray Grey = True
(==) Grey Gray = True
(==) a b = (a == b)
because this leads to an infinite recursion, is basically underdefined.
Is there a way out?
(No, I don't want to use data Colour = Colour String
or similar. I want the valid colours to be represented as an enumeration, such providing automatic validation, but want to allow spelling variation for the end users of the module!)
You can use the derived Enum
instance :
data ColourName = Gray | Grey | ...
deriving (Read, Show, Enum)
instance Eq ColourName where
Gray == Grey = True
Grey == Gray = True
a == b = fromEnum a == fromEnum b
Edit: You can also use PatternSynonyms
with GHC 7.8+. It works like a smart constructor, but can also be used in pattern matches.
pattern Gray = Grey
Do not do this. It won't work well with pattern matching. It will break something like
f Gray = g
f x = h
because pattern matching does not care about your Eq
instance.
By break, I mean it won't have the behavior you want, since f Grey
would end up calling h
rather than g
, even though you would expect for f x == f y
for all x == y
. This means the programmer has to explicitly remember to make cases for both f Gray
and f Grey
which is just dumb.
If you are determined to have an ugly hack to allow for alternate spellings, I suppose you can do
#define Gray Grey
with CPP enabled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With