I've found Never
very helpful when working with generic types. But its usefulness is limited by the fact that it doesn't conform to Equatable
and Hashable
. I'd like to add those conformances to the standard library.
Consider the following result type:
enum Result<Value, Error> {
case success(Value)
case failure(Error)
}
extension Result: Equatable where Value: Equatable, Error: Equatable {
static func == (lhs: Result, rhs: Result) -> Bool {
switch (lhs, rhs) {
case let (.success(lhs), .success(rhs)):
return lhs == rhs
case let (.failure(lhs), .failure(rhs)):
return lhs == rhs
case (.success, .failure), (.failure, .success):
return false
}
}
}
extension Result: Hashable where Value: Hashable, Error: Hashable {
var hashValue: Int {
switch self {
case let .success(value):
return value.hashValue
case let .failure(error):
return error.hashValue
}
}
}
The conditional conformances to Equatable
and Hashable
can be very useful for testing results or putting them in collections.
It's often also convenient to use Never
to represent something that always succeeds (Result<_, Never>
) or always fails (Result<Never, _>
).
Unfortunately, those don't play well together. Either (1) Result
needs to add 2 more Equatable
and Hashable
conformances for when values or errors are Never
or (2) Never
itself needs to be Equatable
and Hashable
.
This isn't unique to Result
. I've run into this with other enum
s and even with classes that are generic over optional values.
Writing these conformances for Never
is easy:
extension Never: Equatable {
public static func == (lhs: Never, rhs: Never) -> Bool {
switch (lhs, rhs) {
}
}
}
extension Never: Hashable {
public func hashValue: Int {
switch self {
}
}
}
But adding them yourself is problematic—especially if you're writing code in a shared library. So I'd like to add these conformances to the standard library.
(Ideally, these implementations could be synthesized by the compiler. But that's not possible today.)