So I wrote this program and everything works fine ;) I would like to improve it. I would also be able to compile two different time sets with the use of /= and get True as an result. I am a little bit confused.
data Time = Localtime {hour, minute :: Int}
| Globaltime {hour, minute, difference :: Int}
| LocaltimeAM {hour, minute :: Int, am :: Bool}
deriving Show
same :: Time -> Time -> Bool
same u1 u2 = (h u1) == (h u2)
where
h :: Time -> (Int, Int) -- (Int, Int) = (hour, minute)
h (Localtime h m) = (h, m)
h (Globaltime h m d) = ((h+d+24) `mod` 24, m)
h (LocaltimeAM h m am) = (h + (if am then 0 else 12), m)
To answer the question in the title:
Can I use
==
and/=
without usingEq
?
You could - technically speaking - explicitly hide the Eq
typeclass in the prelude, and then define a (==)
and (/=)
function yourself, but that would be a bad idea, since it would mean that you can no longer compare two integers with (==)
.
What you probably want is to make Time
an instance of the Eq
typeclass, such that you can from now on write time1 == time2
. We can make it an instance like:
h :: Time -> (Int, Int) -- (Int, Int) = (hour, minute)
h (Localtime h m) = (h, m)
h (Globaltime h m d) = ((h+d+24) `mod` 24, m)
h (LocaltimeAM h m am) = (h + (if am then 0 else 12), m)
instance Eq Time where
t1 == t2 = (h t1) == (h t2)
Haskell will automatically write the (/=)
function for us (as the opposite of (==)
), or you can decide to write the (/=)
version, and then Haskell will write the (==)
version. Of course you can also implement both.
Making types a member of a typeclass actually can be useful. Take for example the nub :: Eq a => [a] -> [a]
function. It requires that the type a
is a member of the Eq
typeclass, and performs some sort of "uniqness" filter: you provide it a list of elements, and it returns a list of non-equal elements. Now without any work to define a nub
function for your Time
type, by making Time
an instance of the Eq
type class, you can use nub
on a list of Time
s.
Of course you can not simply make a type an instance of all possible type classes. You should only make types an instance of the Eq
typeclass if you can check if two items are the same (and there should thus be a "reasonable" idea when two items are equal). Furthermore most of these typeclasses come with "contracts": for example an equality relation (like defined by (==)
) should be reflexive, symmetric, and transitive.