[swift-evolution] [Discussion] Additional generics specialization

Haravikk swift-evolution at haravikk.me
Mon Jul 18 05:18:29 CDT 2016

> On 18 Jul 2016, at 08:04, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote:
> This is something additional, but I’m curios about how the community feels about it.
> I recently come across the issue where conforming to Hashable wasn’t enough to thecke if two instances of the same generic type were equal.
> I had additionally provide myself the != function.
> public func !=<T, U>(lhs: SomeTypeName<T>, rhs: SomeTypeName<U>) -> Bool {
>     return lhs.hashValue != rhs.hashValue
> }
> I wondered if Swift can ever get generic specialization like this:
> public func !=<T : Hashable, U, V>(lhs: T<U>, rhs: T<V>) -> Bool {
>     return !(lhs.hashValue == rhs.hashValue)
> }
> This function in stdlib would fill the gap. Or we need an extra protocol GenericHashable which includes !=.
What exactly is the problem you're trying to solve here? Hash values being equal is not a guarantee of equality, so what you're doing with this operator is masking what's going on which I'm not sure is a good idea. If you need to compare hash-values, then compare them, they're already as generic as you can possibly get (since they're always of type Int), otherwise you can't really rely on hash-values from generic types in this way, and shouldn't be hiding them behind the equality operator.

To think of it another way, if two hash-values are equal, then the two values *might* be equal, but you still have to test them further to be sure. You can only rely on the hash-value in this way if you have control of the implementation details, which you can only guarantee when the values you are comparing are the same type, or from a family of types that you control (as you say, a protocol could do this, by requiring that hash-values are unique within some well-defined domain).

I feel like this is seeking a solution that is a workaround to a protocol that has no associatedtype, as the problem you're describing is essentially already solved by generic constraints. For example, if you were working with Iterators you can define things like:

	func someFunc<I1:IteratorProtocol, I2:IteratorProtocol where I1.Element:Hashable, I2.Element:Hashable>(lhs:I1, rhs:I2) -> Bool {
		return lhs.next()?.hashValue == rhs.next()?.hashValue

Probably a useless example, but it shows how generic constraints achieve this already, but they require a protocol that is intended to expose an internal detail (the Element associatedtype), this is not what Hashable is for, Hashable is for reducing any conforming type down to an Int, with no guarantee of that value being unique.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160718/f82bf106/attachment.html>

More information about the swift-evolution mailing list