Understanding Types Union{}

I read the manual about types carefully, but I can’t figure out how to do this.
Let’s two types of data are possible: Vector{Int8} and Vector{Vector{Int8}}
eg [1, 0, 1] and [[1, 1], [0]]

Following the recommendations, I wrote two implementations:
some_calc(vec::Vector{Int8}) and
some_calc(vec::Vector{Vector{Int8}})

They both work efficiently and recognise types.
But there are actions that have to be done anyway,
so there is a main function that should accept both types:

main_calc(vec::???)
…
some_calc(vec)
…
end

I tried to write Vector in place of ???, or just vec without type description -
nothing works. After studying the manual, I thought the right idea was
Union{Vector{Int8}, Vector{Vector{Int8}}}

But surprisingly

typeof([[1,2], [1,3]]) == Union{Vector{Int64}, Vector{Vector{Int64}}} → false
typeof([1,2,3]) == Union{Vector{Int64}, Vector{Vector{Int64}}} → false

I’m tracking the conversion Int64 → Int8 (it’s needed for performance, so there is no problem with it)
But the last results confused me!

PS. Why do I care so much about types? (Maybe it helps new users)
I do complex computations like fractal research.
And found that Julia is great for this, and with strict typing and right memory allocation much faster than Python etc. So Julia rocks!

1 Like

If it’s just a single method you could just declare it like main_calc(vec), so without any type annotations. For more safety/strictness, you could use main_calc(vec::Vector). For even more strictness, you could use union types: main_calc(vec::Vector{<:Union{Int8,Vector{Int8}}}).

1 Like

Thank you that’s work!

typeof([1,2,3]) == Union{Vector{Int64}, Vector{Vector{Int64}}} is false, because Vector{Int64} is not the same type as Union{Vector{Int64}, ...}. You can check for example

julia> isconcretetype(Union{Vector{Int64}, Vector{Vector{Int64}}})
false

julia> isconcretetype(Vector{Int64})
true

The following holds though,

julia> Vector{Int64} <: Union{Vector{Int64}, Vector{Vector{Int64}}}
true

as any type T is a subtype of a Union containing T or some supertype thereof.

Now, the type Vector{<:Union{Int64,Vector{Int64}}} is different as it specifies a vector where each element could be an Int64 or a Vector{Int64}:

julia> Vector{<:Union{Int64,Vector{Int64}}} == (Vector{T} where {T <: Union{Int64, Vector{Int64}}})
true
julia> [1, 2, 3] isa Vector{<:Union{Int64,Vector{Int64}}}
true
julia> [1, 2, 3] isa Union{Vector{Int64},Vector{Vector{Int64}}}
true
# Note: [1, [2], 3] constructs a Vector{Any} thus explicit types are needed here
julia> Union{Int64, Vector{Int64}}[1, [2], 3] isa Vector{<:Union{Int64, Vector{Int64}}}
true
julia> Union{Int64, Vector{Int64}}[1, [2], 3] isa Union{Vector{Int64}, Vector{Vector{Int64}}}
false

I.e., Union{Vector{Int64}, Vector{Vector{Int64}}} requires either a Vector{Int64} or Vector{Vector{Int64}}, but does not allow for mixed element types.