George Matheos
George Matheos

Reputation: 11

Julia--unrecognized subtype of nested unionall

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

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

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

Related Questions