(==) is overrated
06 September 2024When I first learned Haskell, one of the first habits I picked up was
adding deriving (Show, Eq)
to every type definition I
write. Eventually I added Generic
to this list, but if you
looked at my code now, you wouldn’t find Eq
in there
anymore.
To motivate this I’m going to start off with a pretty strong claim: deep equality checking is almost never actually what you want.
If you ever talked to someone working with dependent types, they
probably talked your ear off about equality and they probably had a
point, but that’s not the kind of equality we’re talking about here.
(==)
is not a property you can use in proofs or anything
like that, it’s just a function that lets you check at runtime if two
things are equal. Now I want you to ask yourself: how often do you
actually need this operation on interesting data types?
Integers? Sure. Strings? Yes, although if you’re doing it a lot you should probably intern your strings anyway. But beyond that? There’s really not a lot.
On the flip side, deep equality (the kind deriving Eq
generates) is linear in the size of your data and a great way
to kill your performance. I work on compilers a lot and I deliberately
make sure to never derive Eq
on syntax trees because
checking those for equality is probably the easiest way to create
quadratic runtime behavior.