Here is a demonstration of some behavior of the Julia typesystem.
function mine(x::Vector{Union{Int64, T}}) where T
println(typeof(x))
println(T)
end
julia> mine(Vector{Union{Int64, String}}([1, 2, 3, "hello"]))
Vector{Union{Int64, String}}
String
julia> mine(([1, 2, 3, "hello"]))
Vector{Any}
Any
In the second case, the type is not Vector{Union{Int64, String}}
. It is also not Vector{Union{Int64, Any}}
which might be a sensible next guess for something more general.
Instead, the type is Vector{Any}
.
I have noticed that Vector
s (and presumably other types as well) tend to like to default to T=Any
, unless their arguments match on the type exactly.
To re-phrase the question another way, it seems the core thing to notice here is that the expression [1, 2, 3, "hello"]
produces a Vector{Any}
.
- Q1: Is that by design?
- Q2: Is there a particular reason for this?
The alternative would be for this to evaluate to Vector{Union{Int64, String}}
.
I think I am correct in stating that if it were the latter, then this would be advantageous for the multiple-dispatch system, for two reasons:
- Precision.
T=Union{Int64, String}
more precisely defines what is contained within the vector. By contrast,T=Any
is a less precise statement about what is contained within the vector. It is a more accurate, or correct, statement about what the vector contains. If you were asked in a court of law, this would be a better thing to say. - Specificity. (Meaning less general.) If two functions are defined which take arguments of type
Vector{Union{Int64, String}}
andVector{Any}
, then we have lost the ability to dispatch on the more specific version. (Which is forT=Union{Int64, String}
.
One final thing to note. I believe I am correct in thinking that Vector{Any}
is not a supertype of Vector{Union{Int64, String}}
despite the fact that Any
is a supertype of Union{Int64, String}
. This is because the types must be organized into a tree structure, which does not have enough flexibility to fully describe whether one type is compatible with another rather than just being a subtype of another.
Also note that Any
is a supertype of Vector{<anything>}
, but the Julia type system stops at the level of Vector{Any}
. It doesn’t “promote” this type all the way to Any
. (Is it obvious what I mean here?)
Any <: Vector{Any} <: Vector{Union{...}}
Please do correct me if I am wrong about this.