dying_sphynx
dying_sphynx

Reputation: 1166

When is it appropriate to require only PartialEq and not Eq?

I am reading the Rust book and trying to understand use cases for PartialEq and Eq traits.

I realise that PartialEq is for relations which are not necessarily reflexive (i.e. there can be such x that x != x) and that Eq is a marker trait which says that relation is also reflexive (and now it is a proper equivalence relation).

The books gives an example where PartialEq is not enough and Eq is required: HashMap<K, V> lookups. Indeed, if we use as a key a data type which only implements PartialEq (for example floating point number), we would get in trouble when we try to use NaN as a key, since we won't be able to find it.

Now, I am trying to understand what feature of a lookup makes it require Eq. I may be able to understand it better if I find an example of code which does not require Eq.

The book says that assert_eq! requires only PartialEq so that we are able to compare things for equality. But if we write assert_eq!(f64::NAN, some_code_producing_nan()); in a test, the test will always fail. We have the same basic issue as with using a PartialEq key in a HashMap, but for some reason it is considered appropriate here.

What is an example of a reasonable function which requires only PartialEq and adding Eq is not desirable/does not make sense?

If there are no such use cases, then why do we care about splitting it into two traits PartialEq / Eq? Haskell, for example, just has Eq.

Upvotes: 29

Views: 6751

Answers (1)

SpencerPark
SpencerPark

Reputation: 3506

Deciding when to use PartialEq vs Eq should be based on whether the use requires that x == x.

The question is not about whether it is possible to compare x to x but rather if that comparison happens, does the use depend on x==x always holding? If the answer is yes, use Eq. Otherwise prefer the weaker constraint PartialEq.

assert_eq!doesn't depend on x==x always holding so there is no need to force that constraint on the caller. As OP succinctly mentioned 2 examples in the comments:

if we do assert_eq!(NAN, produces_nan()) - it's our problem that it gives false, but if we do a lookup of a NAN key in a HashMap, it would be a problem of the HashMap, because it would violate its lookup contract (that it should be able to find all the keys put in the map)

Upvotes: 32

Related Questions