Reputation: 11
While writing a function with the following signature,
f(x::Vector{Tuple{Vector{<:Real}, Vector{<:Real}}})
I ran into an error I do not understand. I tried calling this function f
on z
, defined as follows:
z = [([1,2], [3,4])]
(This is an array of tuples, where each tuple contains two arrays of real numbers; z
as defined above only contains one such tuple.)
The type of z
is
Array{Tuple{Array{Int64,1},Array{Float64,1}},1}
(as found by calling typeof(z)
). I had expected this to be a subtype of
Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}
, the type in the function f
above.
However, when I run the code
z::Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}
I see the following error:
ERROR: TypeError: in typeassert, expected Array{Tuple{Array{#s6,1} where #s6<:Real,Array{#s5,1} where #s5<:Real},1}, gotArray{Tuple{Array{Int64,1},Array{Float64,1}},1}
Likewise, I get a method error when calling f(z)
. Why isn't Array{Tuple{Array{Int64,1},Array{Int64,1}},1}
a subtype of Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}
?
Upvotes: 1
Views: 152
Reputation: 69939
The reason is that:
julia> Tuple{Array{Int64,1},Array{Int64,1}} <: Tuple{Vector{<:Real}, Vector{<:Real}}
true
but clearly:
julia> Tuple{Array{Int64,1},Array{Int64,1}} >: Tuple{Vector{<:Real}, Vector{<:Real}}
false
and becasue types in Julia (except a Tuple
, but here we have a Vector
) are invariant (see here), you have that Vector{S}
is not as subtype of Vector{T}
even if S <: T
.
so you need to write one additional subtyping qualification:
f(x::Vector{<:Tuple{Vector{<:Real}, Vector{<:Real}}})
and similarly:
julia> z::Vector{<:Tuple{Vector{<:Real}, Vector{<:Real}}}
1-element Array{Tuple{Array{Int64,1},Array{Int64,1}},1}:
([1, 2], [3, 4])
or extract the parameter using where
:
julia> f2(x::Vector{Tuple{Vector{T}, Vector{T}}}) where {T<:Real} = x
f2 (generic function with 1 method)
julia> f2(z)
1-element Array{Tuple{Array{Int64,1},Array{Int64,1}},1}:
([1, 2], [3, 4])
or
julia> f3(x::Vector{Tuple{Vector{T}, Vector{S}}}) where {T<:Real, S<:Real} = x
f3 (generic function with 1 method)
julia> f3(z)
1-element Array{Tuple{Array{Int64,1},Array{Int64,1}},1}:
([1, 2], [3, 4])
(choose the first of second form against your decision if two elements of the tuple must have the same type or not)
Upvotes: 2