方法与嵌套类型限制不匹配

时间:2014-08-25 16:30:15

标签: julia dispatch

我有这个简单的方法来计算向量集合的加权平均值

function meanw{T <: Number}(x::AbstractArray{AbstractVector{T}, 1}, w::AbstractVector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

但是当我尝试使用它时,调度与我的方法不匹配。

ERROR: `meanw` has no method matching meanw(::Array{Array{Float64,1},1}, ::Array{Float64,1})

我怀疑在涉及嵌套时我误解了如何使用类型限制。我应该如何重写此功能以匹配我的收藏?

P.S。

我知道矢量和数组是相同的,但差异化使得函数的使用方式更加清晰。

3 个答案:

答案 0 :(得分:4)

因此,如果您重写代码以使用具体的类型

function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::Vector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

这也有效

function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::AbstractVector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

这不起作用

function meanw{T <: Number}(x::Array{AbstractVector{T}, 1}, w::AbstractVector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

这又行了

function meanw{T <: Number}(x::AbstractArray{Vector{T}, 1}, w::AbstractVector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

我们在这里遇到的问题在parametric types

下的Julia手册中有所描述
  

最后一点非常重要:

     

即使Float64&lt;:Real我们也没有Point {Float64}&lt;:   点{实}。

     

换句话说,在类型理论的说法中,朱莉娅的类型   参数是不变的,而不是协变(甚至是   逆变)。这是出于实际原因:而任何实例   Point {Float64}在概念上可能就像Point {Real}的实例一样   好吧,这两种类型在记忆中有不同的表现形式:

这实际上有效吗

function meanw{T <: Number, V <: AbstractVector}(x::AbstractArray{V, 1}, w::AbstractVector{T})
  x̄ = sum(x .* w)
  x̃ = map(z -> z - x̄, x)
  x̄, x̃
end

但真正的问题是你为什么要这样做? 只要输入是良好类型且函数本身是类型稳定的,Julia编译器即使没有类型注释也能够生成有效的代码。类型注释仅用于多次发送,而合同用于指定函数实际可以处理的内容,但由于广泛的类型系统,这在Julia中是非常困难的。

答案 1 :(得分:2)

根本问题是

julia> Vector{Vector} <: Vector{AbstractArray}
false

你正在传递矢量向量。我将其重写为

function meanw{T<:Number,S<:Number}(x::Vector{Array{T}}, w::Vector{S})
    x̄ = sum(x .* w)
    x̃ = map(z -> z - x̄, x)
    x̄, x̃
end
例如,

允许Float64 xInt w。或者不要限制它 - 无论如何它可能是不必要的,因为它不会使它变得更快并且只是一种防御性的编码事物。

答案 2 :(得分:1)

Julia是一种快速发展的语言,每一代人都会推出新功能,并且需要对Q&amp; As As进行审核。

重要

julia> VERSION
v"0.6.0-dev.2259"

Julia的一个先进功能是其调度系统。 (excellent reading about multiple dispatch)。 现在,由于this merge(2017-1-16 v0.6.0),用户可以从三角调度 (read why is it useful?)的新功能中受益。 在这里,我们需要解决为两个参数编写泛型方法的问题:

  1. 数字w
  2. 的一维数组(一般向量)
  3. 数字x
  4. 的一般向量的一般数组

    @wallnuss的答案涉及4种方法都可以。这是第一个:

    function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::Vector{T}) info("both are Vector for the same element-type: $T") end

    julia> meanw([[1],[2]], [1])
    INFO: both are Vector for the same element-type: Int32
    

    以上非常具体主要是因为它不包括AbstractVector的不同子类型,例如:

    julia> (typeof(spzeros(3)) |> supertype |> supertype) <: AbstractVector #=> true
    

    所以定义了第二个:

    function meanw{T <: Number}(x::Array{Vector{T}, 1}, w::AbstractVector{T}) info("an Array of Vectors and an AbstractVector sub-type both with the same element-type: $T") # end

    以上:

    julia> meanw([[1.],[2]], spzeros(3))
    INFO: an Array of Vectors and an AbstractVector sub-type both with the same element-type: Float64
    

    更通用的方法:

    function meanw{T <: Number}(x::AbstractArray{Vector{T}, 1}, w::AbstractVector{T}) info("an AbstractVector subtype of Vectors and an AbstractVector sub-type both with the same element-type $T") end

    即使采用最新方法,也无法完成某些方案:

    julia> meanw([spzeros(3) for i=1:3], spzeros(3)) #=> Error
    julia> meanw([[1],[2]],[1.]) #=> Error
    

    因此,以上所有内容都更具体

    function meanw{T <: Number, V <: AbstractVector}(x::AbstractArray{V, 1}, w::AbstractVector{T}) info("an AbstractVector of AbstractVector sub-type with Any element and an AbstractVector sub-type of Number") end

    似乎最后一种方法涵盖了所有可能的情况,但它比可能需要的更通用。:

    julia> meanw([[""],[2]],[1.]) #=> Not enough restriction for element type of first AbstractVector
    INFO: an AbstractVector of AbstractVector sub-type with Any element and an AbstractVector sub-type of Number
    

    现在有了新的三角形功能,我们可以写:

    function meanw{T <: Number, V <: AbstractVector{T}}(x::AbstractArray{V, 1}, w::AbstractVector{T}) info("an AbstractVector of AbstractVector sub-type and an AbstractVector subtype both for same sub-type of Number (triangular)") end

    检查方法优先级:

    julia> methods(meanw)
    # 5 methods for generic function "meanw":
    meanw{T<:Number}(x::Array{Array{T,1},1}, w::Array{T,1}) in Main at REPL[1]:2
    meanw{T<:Number}(x::Array{Array{T,1},1}, w::AbstractArray{T,1}) in Main at REPL[22]:2
    meanw{T<:Number}(x::AbstractArray{Array{T,1},1}, w::AbstractArray{T,1}) in Main at REPL[24]:2
    meanw{T<:Number,V<:AbstractArray{T<:Number,1}}(x::AbstractArray{V,1}, w::AbstractArray{T,1}) in Main at REPL[41]:2 
    meanw{T<:Number,V<:(AbstractArray{T,1} where T)}(x::AbstractArray{V,1}, w::AbstractArray{T,1}) in Main at REPL[39]:2
    

    最新的方法已经占据了第四位,因为它比前者更具体。

    julia> meanw([spzeros(3) for i=1:3], spzeros(3))
    INFO: an AbstractVector of AbstractVector sub-type and an AbstractVector subtype both for a same sub-type of Number (triangular)
    

    但是meanw([[2],[2]],[1.])仍然针对更通用的方法(第5节)。我们定义另一种方法:

    function meanw{T <: Number, W <: Number, V <: AbstractVector{W}}(x::AbstractArray{V, 1}, w::AbstractVector{T}) info("an AbstractVector of AbstractVector sub-type and an AbstractVector sub-type both for Number (triangular)") end

    julia> meanw([[2],[2]],[1.])
    INFO: an AbstractVector of AbstractVector sub-type and an AbstractVector sub-type both for Number (triangular)