I’ve defined two `==`

methods for a custom type, and they work, but I was a bit surprised that:

- There is not a symmetry fallback for == as there is for promote_rule
- There is not a promotion fallback for ==

The code below is reproducible and contains inline comments showing what results I get at each step. The Tape definition and methods are simplified.

Questions:

- Is the expected way to define
`==`

for two types just to define two methods`==(::A, ::B)`

and`==(::B, ::A)`

? - Are the fallbacks I suggest above actually terrible ideas?

Thanks!

```
# I want to define a new Vector-ish type and an equality method for it
# Aside: how do I add methods to == without this? I was expecting Base.== to work
import Base: ==
struct Tape{T}
initial::AbstractVector{T}
additional::AbstractDict{T,T}
end
Tape(initial::AbstractVector{T}) where T = Tape(initial, Dict{T, T}())
# I want vec == Tape to work
function ==(a::Tape, b::Tape)
a.initial == b.initial && a.additional == b.additional
end
# These aren't required for later steps, either,
# I was just expecting them to work with a Base fallback
# that doesn't actually exist ;)
Base.convert(::Type{Tape{T}}, v::AbstractVector{T}) where T = Tape(v)
Base.promote_rule(::Type{Tape{T}}, ::Type{<:AbstractVector{T}}) where T = Tape{T}
Tape([1]) == [1] # false
[1] == Tape([1]) # false
# I was expecting promotion and convertion to make this unnecessary
function ==(a::Tape, v::AbstractVector)
isempty(a.additional) && a.initial == v
end
Tape([1]) == [1] # true
[1] == Tape([1]) # false
# I was expecting a symmetry definition in Base to make this unnecessary
(==)(a::AbstractVector, b::Tape) = b == a
Tape([1]) == [1] # true
[1] == Tape([1]) # true
```