在编写具有以下签名的函数时,
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}}}
的子类型?
答案 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])
(如果元组的两个元素必须具有相同的类型,则根据您的决定选择第二种形式的第一个形式)