Search code examples
swifthashidentityequalitysemantics

Should equality imply equal hash values?


I'm currently working on a graph data type, and in that context I have thought a lot about semantic problems concerning identity and equality.

My situation is now the following. I have a Vertex type:

final class Vertex<T>: Hashable {

  static func ==(lhs: Vertex, rhs: Vertex) -> Bool { 
    return lhs === rhs
  }

  var value: T

  var hashValue: Int { 
    return ObjectIdentifier(self).hashValue 
  }

}

As you can see equality is determined by identity. I have done this for reasons specific to the graph data type, but what it basically comes down to, is the fact that vertices should be viewed by their identity and therefore only be viewed as equal if they are the same (identical) vertex.

Now the hash value is also determined by identity (using the ObjectIdentifier). This seemed to be the easiest way of getting a hash value, and also seemed to align well with the conception of equality for this type.

But this got me thinking...
Would it be semantically "incorrect" (or illogical if you will) to determine the hash value by, let's say, the value property (if T conformed to Hashable).
In that case two Vertexs could have equal hash values consistently (not just for one invocation of the program), without being considered equal. And that doesn't seem right.

So in turn: Is it sensible to say that equality of instances should imply equality of their hash values?


Solution

  • From the documentation for Hashable:

    "A hash value, provided by a type’s hashValue property, is an integer that is the same for any two instances that compare equally. That is, for two instances a and b of the same type, if a == b then a.hashValue == b.hashValue. The reverse is not true: Two instances with equal hash values are not necessarily equal to each other."

    In other words, if == returns true, hashValue must return the same value for both objects.