函数中julia的抽象类型数组

函数中julia的抽象类型数组,julia,Julia,我试图理解Julia中的输入,但在Array中遇到了以下问题。我写了一个函数bloch_vector_2d(Array{Complex,2});具体的实现是无关紧要的。打电话时,投诉如下: julia> bloch_vector_2d(rhoA) ERROR: MethodError: no method matching bloch_vector_2d(::Array{Complex{Float64},2}) Closest candidates are: bloch_vector_

我试图理解Julia中的输入,但在
Array
中遇到了以下问题。我写了一个函数
bloch_vector_2d(Array{Complex,2})
;具体的实现是无关紧要的。打电话时,投诉如下:

julia> bloch_vector_2d(rhoA)
ERROR: MethodError: no method matching bloch_vector_2d(::Array{Complex{Float64},2})
Closest candidates are:
  bloch_vector_2d(::Array{Complex,2}) at REPL[56]:2
  bloch_vector_2d(::StateAB) at REPL[54]:1
Stacktrace:
 [1] top-level scope at REPL[64]:1
问题是父类型的数组不会自动成为子类型数组的父类型

julia> Complex{Float64} <: Complex
true

julia> Array{Complex{Float64},2} <: Array{Complex,2}
false

julia>Complex{Float64}数组{Complex{Float64},2}julia手册详细讨论了这个问题

引用其中的相关部分:

换句话说,用类型理论的说法,朱莉娅的类型参数是不变的,而不是协变的(甚至是逆变的)。这是出于实际原因:虽然
点{Float64}
的任何实例在概念上也可能类似于
点{Real}
的实例,但这两种类型在内存中有不同的表示:

  • 点{Float64}
    的实例可以紧凑有效地表示为64位值的立即对
  • 点{Real}
    的实例必须能够容纳
    Real
    的任何一对实例。由于作为实数实例的对象可以具有任意大小和结构,因此在实践中,
    点{Real}
    的实例必须表示为指向单独分配的实数对象的一对指针
现在回到您的问题,如何编写方法签名,您有:

julia> Array{Complex{Float64},2} <: Array{<:Complex,2}
true
另请注意,表示法
Array{虽然“它是如何工作的”讨论已在另一个答案中完成,但实现方法的最佳方法如下所示:

function bloch_vector_2d(a::AbstractArray{Complex{T}}) where T<:Real
    sum(a) + 5*one(T)  # returning something to see how this is working
end

这更多的是一个评论,但我会毫不犹豫地发布它。这个问题经常出现。我会告诉你为什么会出现这种现象

一个
Bag{Apple}
是一个
Bag{Fruit}
,对吧?因为,当我有一个
juice压{Fruit}
,我可以给它一个
Bag{Apple}
来做一些果汁,因为
Apple
s是
水果

但现在我们遇到了一个问题:我加工不同水果的果汁厂出了故障。我订购了一个新的
果汁压榨{fruit}
。现在,我不幸收到了一个替代品
果汁压榨{Lemon}
——但是
柠檬
水果
s,所以肯定是
果汁压榨{Lemon code}
是一种
果汁压{Fruit}
,对吗

然而,第二天,我给新的印刷机喂苹果,机器爆炸了。我希望你明白为什么:
JuicePress{Lemon}
不是a
JuicePress{Fruit}
。相反:a
JuicePress{Fruit}
JuicePress{Lemon}
--我可以用水果不可知论的压榨机压榨柠檬!不过他们可以给我送一个
果汁压榨机{Plant}
,因为
水果
s是
植物
s

现在我们可以更抽象了。真正的原因是:函数输入参数是逆变的,而函数输出参数是协变的(在理想化的设置中)。2。也就是说,当我们

f : A -> B
然后我可以传入
A
的超类型,最后得到
B
的子类型

(Tree -> Apple) <: (Tree -> Fruit)
这就是我们如何得出其他答案的原因


1元组除外,但这很奇怪


2这个术语来源于:
Hom
-函子在第一个参数中是逆变的,在第二个参数中是协变的。通过“健忘”函子可以直观地实现子类型化,从类别
Typ
下的
Typ
es的偏序集,或者仅仅是
bloch\u向量_2d(a::AbstractMatrix){谢谢!我想我明白了。问题是julia是面向功能的(旨在操纵像Juice Press这样的类别中的箭头,而不仅仅是Bag).它的设计真的是基于范畴理论吗?谢谢你也编辑了我的问题!不,不是出于动机。这个术语来自那里,它适合更大的图景,但问题在每个具有参数类型和子类型的系统中都会自行产生。我想写
(Tree->Apple)Fruit可能不会那么模棱两可)
。我花了一分钟摸索那条线。
f : A -> B
(Tree -> Apple) <: (Tree -> Fruit)
(Fruit -> Juice) <: (Apple -> Juice)
makejuice(::JoicePress{>:T}, ::Bag{<:T}) where {T}