Reputation: 141
I am implementing an instance Eq
for MyNum
data type that has Fractions and Mixed Numbers as data constructors (each one with its own arguments).
I am also using a helper
function to convert from MyNum
to Rational
. This should help me reduce fractions when doing comparisons in the instance Eq
.
The problem is I am getting stuck when creating the instance Eq
and I am not sure whether I also have to define a new class Eq
for the MyNum
data type. The general purpose of the Eq
is to compare whether two fractions are equal when simplified with the helper method. Here is what I have so far:
Data Type and Constructors:
data MyNum = Fraction {num :: Integer, denom :: Integer}
| Mixed {whole :: Integer, num:: Integer, denom :: Integer}
Helper:
helper :: MyNum -> Rational
helper (Fraction num denom) = (fromIntegral num ) / (fromIntegral denom)
Current Eq
:
instance (Eq n d) => Eq (MyNum n d) where
Fraction n d == Fraction n d = True
-- Mixed _ _ _ == Mixed _ _ _ = True
The above Eq
code throws the following error:
MyNum.hs:29:16: error: * Conflicting definitions for `d' Bound at: MyNum.hs:29:16 MyNum.hs:29:32 * In an equation for `==' | 29 | Fraction n d == Fraction n d = True | ^^^^^^^^^^^^^^^^^
Upvotes: 1
Views: 1034
Reputation: 476574
The reason this happens is because you use n
and d
twice in the head of your ==
method definition, which is not allowed.
Both Fraction n d
and Fraction n d
in Fraction n d == Fraction n d = True
are patterns, and using the same variable in more than one pattern on the left of the =
sign in not allowed.
You would also need to write the type constraints as (Eq n, Eq d) =>…
, and not Eq n d
, but here it makes no difference since you do not use type parameters anyway, so no Eq
constraint is needed at all -- the type of the values used by your MyNum
type, which are all Integer
s, already is an instance of Eq
:
instance Eq MyNum where
Fraction n1 d1 == Fraction n2 d2 | n1 == n2 && d1 == d2 = True
-- …
Prolog, which works with unification indeed allows us to use the same variable multiple times in the head, to indicate equality.
But Haskell works with pattern matching, and it is therefore not entirely clear what reusing the same variable would mean, especially since not every type is an instance of Eq
.
Upvotes: 4
Reputation: 116139
You might want to exploit your helper
function to convert both MyNum
s into Rational
s so that you can compare them:
instance Eq MyNum where
x == y = helper x == helper y
Your type MyNum
does not take any parameters, so you can't write Eq (MyNum n d)
. The n
and d
are values, arguments for the Fraction
data constructor, not the type. Since these values are handled by the helper, we don't need to care about them in the instance definition either.
Note that, for the above instance to work, helper
must deal with both forms of number, Fraction
and Mixed
.
helper:: MyNum -> Rational
helper (Fraction num denom) = fromIntegral num / fromIntegral denom
helper (Mixed whole num denom) = ...
Upvotes: 3