Is the `Ord` implementation inconvenient for the type?

Trying to wrap my head around Rust again.

So, I have a type, let it be a new type for the purpose of simplicity:

struct MyType(isize); 

And I want to implement Ord .

So I:

 impl Ord for MyType { fn cmp(&self, &other: Self) -> Ordering { let MyType(ref lhs) = *self; let MyType(ref rhs) = *other; lhs.cmp(rhs) } } 

Now, when I want to compare two variables of my types, I get the following errors:

 <anon>:4:5: 10:6 error: the trait `core::cmp::Eq` is not implemented for the type `MyType` [E0277] <anon>:4 impl Ord for MyType { <anon>:5 fn cmp(&self, &other: Self) -> Ordering { <anon>:6 let MyType(ref lhs) = *self; <anon>:7 let MyType(ref rhs) = *other; <anon>:8 lhs.cmp(rhs) <anon>:9 } ... <anon>:4:5: 10:6 error: the trait `core::cmp::PartialOrd` is not implemented for the type `MyType` [E0277] <anon>:4 impl Ord for MyType { <anon>:5 fn cmp(&self, &other: Self) -> Ordering { <anon>:6 let MyType(ref lhs) = *self; <anon>:7 let MyType(ref rhs) = *other; <anon>:8 lhs.cmp(rhs) <anon>:9 } ... 

Now when I implement PartialEq, Eq and PartialOrd (gt (), lt (), eq (), ge (), le () ...) everything works fine. What a mess. BUT: If I provided cmp , we can output functions such as lt() and eq ! This is redundant! I do not like this!

When you look at the docs , I see this in the definition of Ord:

 pub trait Ord: Eq + PartialOrd<Self> 

Now it looks like the trait inherits from eq and PartialOrd . Why can't a trait provide a default implementation for required methods from inherited traits using the cmp function? I don’t know how the heredity hell works (googling didn’t help, which is common when searching by rust: \), but I think this is what should be possible.

How is it done in rust? I hope not so ...

+8
traits rust ord
source share
2 answers

Well, for your specific case, I would just use #[derive] :

 #[derive(Ord,PartialOrd,Eq,PartialEq,Debug,Copy,Clone)] struct MyType(isize); fn main() { let a = MyType(5); let b = MyType(6); println!("{:?}", a.cmp(&b)) } 

If you need a special case for your implementation of Ord , you will have to write this code, nothing saves us there! You can still get implementations for other features if it makes sense to do this.

The other part of your question is ambiguous, so I will answer both paths that I read:

Why can't Ord be provided automatically with PartialOrd ?

Look at the docs for PartialOrd and Ord .

PartialOrd says: "Comparison must satisfy antisymmetry and transitivity," while Ord says: "types that form a general order." These are mathematical terms, and I will not work as well as Wikipedia in describing them.

However, as an example, we can use floating point numbers. Floats have the special meaning of NaN . Comparison with this value is difficult. For example, all 1.0 < NaN , 1.0 == NaN and 1.0 > NaN are false! They do not form a general order, but we can compare one value with another. That's why PartialOrd exists - so that we can compare types like this. PartialEq , by the way, exists for the same reasons.

We cannot define Ord in terms of PartialOrd , because we do not have the appropriate guarantees regarding the base types. This is a system like Rust, saving us from mistakes!

Why PartialOrd n't PartialOrd be automatically provided with Ord ?

The problem is that there are more types of PartialOrd than they are Ord . If we required everything to be Ord , then we could not compare any floating point values, because they do not have a common order. Or we would have to refuse the full order and lose the security that it provides.

when I implement PartialOrd (gt (), lt (), eq (), ge (), le () ...)

Note that PartialOrd has standard implementations, you need to implement cmp . The rest exist for ease of use, or perhaps because of performance.

+6
source share

First, you can only implement PartialOrd::partial_cmp , since lt , le , gt and ge have default implementations. Also, if you implement Ord , you can just implement cmp , as usual, and partial_cmp will just become Some(self.cmp(other)) .

However, if you only want to delegate any field concept of equality and ordering, then it is much better and easier to get:

 #[derive(PartialOrd,Ord,PartialEq,Eq)] struct MyType(isize); 
+5
source share

All Articles