# Should custom hash functions distinguish types?

**URL:** <https://discourse.julialang.org/t/should-custom-hash-functions-distinguish-types/106984>\
**Category:** General Usage\
**Tags:** dictionary, hash\
**Created:** [December 1, 2023, 10:22am UTC](https://discourse.julialang.org/t/should-custom-hash-functions-distinguish-types/106984 "2023-12-01T10:22:22Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [December 1, 2023, 10:22am UTC](https://discourse.julialang.org/t/should-custom-hash-functions-distinguish-types/106984/1 "2023-12-01T10:22:22Z")

</div>

Suppose my package define two struct types `A` and `B`, each containing just a single field called `data`. Then I overload `Base.hash` as follows:

```julia
import Base: hash

hash(a::A, i) = hash(a.data, i)

hash(b::B, i) = hash(b.data, i)

```

This is OK for my own use cases, since I use dictionaries containing only keys of type `A` or only keys of type `B`. However, a future user of the package may want to construct a `Dict{Union{A, B}, T}`, where the keys can be of either type. This becomes problematic, because the the hash function doesn’t distinguish the two types, so the hashes will collide whenever `a.data` and `b.data` are the same.

Is there any style guide or informal advice regarding such practices with custom hash functions?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [December 1, 2023, 11:09am UTC](https://discourse.julialang.org/t/should-custom-hash-functions-distinguish-types/106984/2 "2023-12-01T11:09:59Z")

</div>

It depends on whether you consider the type important for equality or not. If you do, you have to incorporate the type into the hash as well, if you don’t, you don’t need to.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [December 1, 2023, 11:16am UTC](https://discourse.julialang.org/t/should-custom-hash-functions-distinguish-types/106984/3 "2023-12-01T11:16:17Z")

</div>

Hash equality does not imply object equality, see docstrings for `hash` and `isequal`, for example.

If the hash don’t distinguish between your `A` and `B` types above that only means a higher probability for hash collisions. It is still fine to have `A(1)` and `B(1)` in the dictionary; they will hash to the same value, but then `isequal` will distinguish them.

```julia
julia> struct A
           data::Int
       end
       Base.:(==)(a1::A, a2::A) = a1.data == a2.data
       Base.hash(a::A, h::UInt) = hash(a.data, h)

       struct B
           data::Int
       end
       Base.:(==)(b1::B, a2::B) = b1.data == b2.data
       Base.hash(b::B, h::UInt) = hash(b.data, h)

julia> a = A(1); b = B(1);

julia> hash(a) == hash(b)
true

julia> a == b
false

julia> Set((a, b))
Set{Any} with 2 elements:
  A(1)
  B(1)

```
