Julia-嵌套的unionall的无法识别的子类型

时间:2018-12-24 10:13:20

标签: julia

在编写具有以下签名的函数时,

f(x::Vector{Tuple{Vector{<:Real}, Vector{<:Real}}})

我遇到了一个我不明白的错误。我尝试在f上调用此函数z,定义如下:

z = [([1,2], [3,4])]

(这是一个元组数组,其中每个元组包含两个实数数组;上面定义的z仅包含一个这样的元组。)

z的类型是

Array{Tuple{Array{Int64,1},Array{Float64,1}},1}

(通过调用typeof(z)找到)。我曾以为这是

的子类型
Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}

,即上面函数f中的类型。

但是,当我运行代码时

z::Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}

我看到以下错误:

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}

同样,调用f(z)时出现方法错误。为什么Array{Tuple{Array{Int64,1},Array{Int64,1}},1}不是Vector{Tuple{Vector{<:Real}, Vector{<:Real}}}的子类型?

1 个答案:

答案 0 :(得分:2)

原因是:

julia> Tuple{Array{Int64,1},Array{Int64,1}} <: Tuple{Vector{<:Real}, Vector{<:Real}}
true

但很明显:

julia> Tuple{Array{Int64,1},Array{Int64,1}} >: Tuple{Vector{<:Real}, Vector{<:Real}}
false

和Julia中的becasue类型(Tuple除外,但是这里有一个Vector)是不变的(请参见here),而您发现Vector{S}不是Vector{T}的子类型,即使S <: T

所以您需要另外写一个子类型限定:

f(x::Vector{<:Tuple{Vector{<:Real}, Vector{<:Real}}})

并类似地:

julia> z::Vector{<:Tuple{Vector{<:Real}, Vector{<:Real}}}
1-element Array{Tuple{Array{Int64,1},Array{Int64,1}},1}:
 ([1, 2], [3, 4])

或使用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])

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])

(如果元组的两个元素必须具有相同的类型,则根据您的决定选择第二种形式的第一个形式)