I’m a bit curious about the following problem, it’s not a big deal and has an easy solution, but anyway
struct A{T,S}
t::T
s::S
end
struct B{V<:A}
v::Vector{V}
end
b1 = B([A(1,2), A(3,4.0)]) # element type is UnionAll
b2 = B([A(1,2), A(3,4)]) # element type is concrete
function f(b::B{T}) where {T}
T isa UnionAll ? "UnionAll" : Symbol("not UnionAll")
end
The function f checks if the element type of b.v is a UnionAll, and takes different code paths.
Is there a way to handle this by dispatch instead of the isa test? I.e. have two methods for f with different signatures?
There’s of course this kludge:
No you can’t dispatch on the type of a type in the same position as dispatching on the type itself.
Your solution with a second function is probably the neatest way if you really want to use dispatch, though if I were you I’d just branch like you did originally.
v::Vector{Vector{Int64}} = [[1]]
function f_okay(v::Vector{T}) where T
T
end
f_okay(v)
function f_no_support(v::Vector{T}) where T::Vector{<:Integer}
T
end;
f_no_support(v)
The element type of a is A{Int64} which is an “incomplete” type, it’s really A{Int64, S} where S, with a free type variable S, i.e. a UnionAll type:
julia> typeof(eltype(a))
UnionAll
julia> dump(A{Int})
UnionAll
var: TypeVar
name: Symbol S
lb: Union{}
ub: abstract type Any
body: struct A{Int64, S} <: Any
t::Int64
s::S
julia> dump(A{Int,S} where S)
UnionAll
var: TypeVar
name: Symbol S
lb: Union{}
ub: abstract type Any
body: struct A{Int64, S} <: Any
t::Int64
s::S
And I wanted to know if this can be picked up by dispatch, something like
function f(b::B{T}) where {T isa UnionAll} # unsupported
...
end
to distinguish it from when the element type (T) is e.g. A{Int, Int} or A{Int, Float64}, which is a “complete” DataType not a UnionAll.