I asked this question on the Julia Slack and got a reasonable fix but I am wondering if there is a better solution (specifically one that works entirely via multiple dispatch).
Suppose I have the following set up:
abstract type A{T} end
struct B{T} <: A{T} end
struct C{T} <: A{T} end
abstract type D{T} <: A{T} end
struct E{T} <: D{T} end
struct F{T} <: D{T} end
I want to define a promotion method so that all subtypes of A
works like the following:
promote_rule(B{Float64}, B{Float32}) -> B{Float64}
and promote_rule
between any two different subtypes (disregarding parameter, so like C{Int64}
is different than E{Int64}
but would be considered the same subtype as C{BigFloat}
) should return an error.
At this point, I have the following solution:
function promote_rule(::Type{T}, ::Type{S}) where {U, V, T<:A{U}, S<:A{V}}
if T == S
T
else
N = typejoin(T, S)
isabstracttype(N) ? error("incompatible types") : N{promote_type(U, V)}
end
end
however, this seems kinda hacky and maybe there are some edge cases where this works when it shouldn’t.
Is there a way to achieve this purely by multiple dispatch?
Just as context, the D
abstract type and its subtypes were included because one suggestion on slack was to check if typejoin(T, S)
was equal to A
, in which case they would be incompatible types. Since there can be any arbitrary subtyping structure with abstract types thrown in, this approach wouldn’t work as we could not know what the lowest common abstract subtype ancestor is between two arbitrary types.