I need to use this data structure data D = C Int Float
and I need to compare it with an Int, for example a::D == 2
.
How can I create an instance to define this kind of Eq ?
Thank you!
I would implement a projection:
getInt :: D -> Int
getInt (C i _) = i
and then compare with it:
getInt myD == 5
you can even include this into a record:
data D = C { getInt :: Int, getFloat :: Float }
if you like
You can't; ==
has signature a -> a -> Bool
, so it can't be used like this.
Using the convertible
package you can define
(~==) :: (Convertible a b, Eq b) => a -> b -> Bool
x ~== y = case safeConvert x of
Right x' -> x' == y
Left _ -> False
(==~) :: (Convertible b a, Eq a) => a -> b -> Bool
(==~) = flip (~==)
instance Convertible Int D where ...
-- or D Int depending on what you have in mind
Without depending on convertible
, you could just define a conversion function either from Int
to D
(and write a == fromInt 2
) or vice versa.
A less recommended route (for this specific case I think it's simply worse than the first solution) would be to define your own type class, eg
class Eq' a b where
(=~=) :: a -> b -> Bool
instance Eq a => Eq' a a where
x =~= y = x == y
instance Eq' D Int where ...
etc.
This can be done, but I doubt you will want to do this. As Alexey mentioned the type of (==)
is Eq a=>a->a->Bool
, so the only way to make this work would be to make 2
have type D
. This may seem absurd at first, but in fact numbers can be made to have any type you want, as long as that type is an instance of Num
instance Num D where
fromInteger x = C x 1.0
There are still many things to work out, though....
First, you need to fully implement all the functions in Num
, including (+)
, (*)
, abs
, signum
, fromInteger
, and (negate | (-))
.
Ugh!
Second, you have that extra Float
to fill in in fromInteger. I chose the value 1.0
above, but that was arbitrary.
Third, you need to actually make D
an instance of Eq
also, to fill in the actual (==)
.
instance Eq D where
(C x _) == (C y _) = x == y
Note that this is also pretty arbitrary, as I needed to ignore the Float values to get (==)
to do what you want it to.
Bottom line is, this would do what you want it to do, but at the cost of abusing the Num
type, and the Eq
type pretty badly.... The Num
type should be reserved for things that you actually would think of as a number, and the Eq
type should be reserved for a comparison of two full objects, each part included.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.