I am trying to define Eq operator for alternative version numbering approach.
type VersionCompound = Maybe Int -- x, 0, 1, 2, ...
type VersionNumber = [VersionCompound] -- x.x, x.0, x.1, x.2, ... , 1.0, 1.1, 1.2, ... 1.x.x, 2.x.x, 3.x.x, ...
instance Eq VersionNumber where
[] == [] = True
(x:[]) == (y:[]) = x == y
(Nothing:xs) == ys = (xs == ys)
xs == (Nothing:ys) = (xs == ys)
It is expected that it returns True
for following cases: x.x.x == x
, 1.x.x == x.1.x.x
, x.1 == 1
, etc. But instead it returns an error:
VersionNumber.hs:58:34:
Overlapping instances for Eq [VersionCompound]
arising from a use of ‘==’
Matching instances:
instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
instance Eq VersionNumber -- Defined at VersionNumber.hs:55:10
In the expression: (xs == ys)
In an equation for ‘==’: (Nothing : xs) == ys = (xs == ys)
In the instance declaration for ‘Eq VersionNumber’
Any ideas how to fix it?
EDIT: My approach to this problem via pattern matching on lists turned out to be incomplete. I wanted to disregard any arbitrary list of x
's (or Nothing
s) on the left hand side of the given version. So, for example, x.x.x.x.x
would be equal to x.x.x
and to x
. Similarly, x.x.x.1
would be equal to x.x.1
and to 1
. If there's an x
in the middle, it won't be thrown away. So, for this case, x.x.1.x.0
would be equal to x.1.x.0
and 1.x.0
. Yet another example: x.1.x.x.0.x
is equal to 1.x.x.0.x
and x.1.x.0.x
is equal to 1.x.0.x
(You just remove x
's on the left side).
What I was struggling with after fixing an error Overlapping instances for Eq [VersionCompound]
is how to get x.x.x == x
-> True
with pattern matching. But, as @WillemVanOnsem brilliantly noted, it should be achieved not via pattern matching, but with function composition.
PS. I personally encourage you to upvote the answer by @WillemVanOnsem because his solution is really elegant, required some effort to come up with and represents the essence of Haskell power.