Result classes do not respect rich comparison
In an equality `A() == B()`, Python first invokes `A.__eq__(a, b)`. If `A` does not understand `B` as a type to which it can do a comparison, [it is supposed to](https://docs.python.org/3/reference/datamodel.html#object.__eq__) return the `NotImplemented` sentinel, which triggers Python to invoke `B.__eq__(b, a)`.
The `Success` and `Failure` classes of `returns.result` do not return `NotImplemented` from their `__eq__` methods and therefore do not allow for a rich comparison with instances of these classes. This is annoying for a number of reason. For example, this make it impossible to implement a shim that would be needed to do a backwards-compatible migration of a custom `MyResult` class hierarchy to the Returns `Result` hierarchy.
See below, where it is impossible to create a `MySuccess` class that is equal to the `Success` class, but only when the Returns class is first.
```python
from dataclasses import dataclass
from typing import Never
from returns import result
class MyResult[Value, Error]:
pass
@dataclass
class MySuccess[Value](MyResult[Value, Never]):
value: Value
def __eq__(self, other):
match other:
case MySuccess(value):
return self.value == value
case result.Success(value):
return self.value == value
case _:
return False
@dataclass
class MyFailure[Error](MyResult[Never, Error]):
error: Error
def __eq__(self, other):
match other:
case MyFailure(error):
return self.error == error
case result.Failure(error):
return self.error == error
case _:
return False
assert MySuccess(10) == result.Success(10)
assert result.Success(10) == MySuccess(10) # Fails
assert MyFailure("error") == result.Failure("error")
assert result.Failure("error") == MyFailure("error") # Fails
```
4 条评论