首页 > 解决方案 > Julia - 嵌套 unionall 的无法识别的子类型

问题描述

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

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}}}

标签: julia

解决方案


原因是:

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 中的类型(除了 a Tuple,但这里我们有 a Vector)是不变的(见这里),你有它Vector{S}不是Vector{T}even if的子类型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])

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


推荐阅读