 # What is the difference between `Eq` and `PartialEq`?

If I impl the Eq as std said:

``````impl Eq for foo {}
``````

What will happend?
And I can’t find any method or notation to use Eq?
will compiler treat Eq just like Partial Eq?

Thank you!

3 Likes

From the documentation:

## Eq

Trait for equality comparisons which are equivalence relations.

This means, that in addition to a == b and a != b being strict inverses, the equality must be (for all a, b and c):

``````reflexive: a == a;
symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
``````

This property cannot be checked by the compiler, and therefore Eq implies PartialEq, and has no extra methods.

## 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.

Formally, the equality must be (for all a, b and c):

``````symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
``````

Note that these requirements mean that the trait itself must be implemented symmetrically and transitively: if T: PartialEq and U: PartialEq then U: PartialEq and T: PartialEq.

What will happen?

You will implement the respective traits for type foo. It is up to you to ensure the contract defined in the documentation is upheld. If you don’t uphold the contract, bad / illogical things might happen.

I can’t find any method or notation to use Eq

Trait Eq inherits trait PartialEq. All it does is refine the contract.

``````a == a // valild assuming type A implements Eq
``````

Will compiler treat Eq just like PartialEq?

As mentioned previously, Eq inherits PartialEq (i.e. PartialEq needs to be implemented for a type for Eq can be implemented). See the book on traits.

5 Likes

The docs for PartialEq say:

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.

Formally, the equality must be (for all a, b and c):

symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.

Whereas the docs for Eq say

Tr ait for equality comparisons which are equivalence relations.

``````This means, that in addition to a == b and a != b being strict inverses, the equality must be (for all a, b and c):

reflexive: a == a;
symmetric: a == b implies b == a; and
transitive: a == b and b == c implies a == c.
This property cannot be checked by the compiler, and therefore Eq implies PartialEq, and has no extra methods.
``````

Mathematically speaking, there are times where you can define equality for most of the values in a type, but not all of them (floating point `NaN`'s can’t compare to anything). A lot of times even though the strict meaning of equality (represented as `Eq`) can’t be used, it still makes sense to try and check whether two things are the same, returning a result that says either we could compare for equality (`Some(true)` and `Some(false)`) or we couldn’t `None`.

I usually just derive `PartialEq` for my types if I want to be able to check whether they look the same using the `==` operator. However sometimes you need much stricter constraints, which is when you use `Eq` (e.g. keys in a hash map).

This `PartialEq` vs `Eq` difference is one of the things which help prevent the issues in javascript when sorting arrays which contain `NaN` or `null`.

2 Likes

So, if I don’t want to all fields be same, should I impl the Eq by myself? or just impl PartialEq?

`Eq` can be thought of as a marker trait, kind of like `Send` and `Sync`. It’s a type-level assertion that the type it’s implemented for provides total equivalence. It doesn’t add any extra API.

If you don’t want all fields to be considered during equality, you’ll need to implement `PartialEq` by-hand. If you also want to assert that this type has total equivalence, you’ll implement `Eq` for it.

2 Likes

Don’t have total equivalance. So, I shouldn’t impl `Eq`?
I impl it because std said: Note that the derive strategy requires all fields are Eq, which isn’t always desired.

Right - don’t impl `Eq` then.

If you’re using derive (i.e. `#[derive(PartialEq, Eq)] struct MyStruct`) then it will require that all fields are `Eq` themselves; this makes sense because deriving these impls just delegates to every single field. For the whole struct to be derivable to `Eq`, all its underlying fields must be `Eq`.

Since you’re not going to be deriving these anyway, it’s not applicable.

I impl the Eq because PartialOrd reqiures Eq.
And actually I’m working on a fraction collection.
When compare begin, I don’t want denominator be zero anymore. So I impl the PartialEq and PartialOrd.
But Eq has no API to impl and it is required by PartialOrd. So, I’m confusing about it.

So, should I just derive it in this case?

`PartialOrd` requires `PartialEq` - where do you see it requiring `Eq`?

Oh, maybe I mixed up everything.
Sorry.

Maybe a bit later, but better than never In order to understand `PartialEq` and `Eq` forget `Rust` for a moment.
Assume we have a simple rule: we can't compare letters with a floating point numbers.

Consider a set `{a,b,c,d}`. Any two elements from the set is (ASCII) comparable with each other. It makes sense to compare `a` with `b`, or `b` with `d`. Hence we may say this set implements `Eq`.

On the other hand, `{a,b,c,d, 1.2, -5.2}` does not implement `Eq` since we can't, for example, compare `a` with '-5.2'. It does not make sense to compare a char with a neg real number. But it implements `PartialEq`, some elements can be compared with each other, e.g. `1.2` with `-5.2` or `a` with `d`.

Furthermore, `Eq` implies `PartialEq`, that is, because 'Eq' requires ALL elements be comparable, while `PartialEq` requires SOME elements be comparable.

2 Likes

This topic was automatically closed 7 days after the last reply. We invite you to open a new topic if you have further questions or comments.