Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

rust

traits

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.

like image 819
dying_sphynx Avatar asked Mar 12 '19 18:03

dying_sphynx


People also ask

What is PartialEq?

Trait for equality comparisons which are partial equivalence relations. This trait allows for partial equality, for types that do not have a full equivalence relation. For example, in floating point numbers NaN != NaN, so floating point types implement PartialEq but not Eq.

How do you check equality in Rust?

We can use the eq(), eq_ignore_ascii_case() and == to compare strings in Rust.


1 Answers

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)

like image 184
SpencerPark Avatar answered Oct 10 '22 22:10

SpencerPark