是否可以创建一个函数,它接受::Vector{DataType}
但是将所有成员约束为从特定抽象类型继承的类型?
示例:
# this code works but does not constrain the type
function foo{D<:DataType}(arr::Vector{D})
...
end
# this is kind of the syntax I'd like, but Type{Int} !<: Type{Integer}
function bar{D<:Type{Integer}}(arr::Vector{D})
...
end
谢谢
答案 0 :(得分:2)
我不确定这是否可以(干净利落)进行编译时检查。您可以考虑使用Val
类型,但这会很混乱,可能会更慢。我想把它作为运行时检查:
julia> function bar{T}(::Type{T}, arr::Vector{DataType})
if all(x->x<:T, arr)
println("ok")
else
println("bad")
end
end
bar (generic function with 1 method)
julia> bar(Integer, [Int,Int32])
ok
julia> bar(Integer, [Int,Int32,Float64])
bad
您的用例是什么?可能有一种更清洁的替代品。
答案 1 :(得分:1)
只是为了澄清function bar{T<:Integer}(arr::Vector{Type{T}}) = println(arr)
无效的原因。
简而言之,这是因为julia's type parameter is invariant 。
首先,看看OP的定义:
function bar{D<:Type{Integer}}(arr::Vector{D})
...
end
正如OP所指出的,这里的问题是Type{Int} !<: Type{Integer}
。
原因是Type{T}
是参数类型,即使Int <: Integer
,我们也没有Type{Int} <: Type{Integer}
。
“记住”(是的,那是讽刺)julia的参数类型的类型参数是不变的,我建议使用这个版本:
function bar{T<:Integer}(arr::Vector{Type{T}})
...
end
好像很好!这次我使用T
代替Type{T}
,所以我不会陷入Type{Int} !<: Type{Integer}
的陷阱。
然而,当我写下评论时,我刚刚陷入另一个坑 - Vector{}
也是参数类型。即使DataType <: Type{T}
,我们也没有Vector{DataType} <: Vector{Type{T}}
。
结果 ,运行bar([Int64, Int32])
时会出错。
julia> bar([Int64, Int32])
ERROR: MethodError: `bar` has no method matching bar(::Array{DataType,1})
julia> methods(bar)
bar{T<:Integer}(arr::Array{Type{T<:Integer},1})
julia> [Int64, Int32]
2-element Array{DataType,1}:
Int64
Int32
DataType
和Type{T}
之间的神秘关系。
# we know that DataType is a subtype of Type{T},
# where T is a `TypeVar` \in [Bottom, Any].
julia> subtypes(Type)
3-element Array{Any,1}:
DataType
TypeConstructor
Union
julia> S = TypeVar(:S, Union{}, Integer, true)
S<:Integer
# but Type{S} is not a subtype of DataType
julia> Type{S} <: DataType
false
julia> Type{S} <: Type
true
因此,我得出结论,在你的案件中::Vector{DataType}
是不可能的。
DataType
没有类型参数。
以下定义不起作用,这似乎是一个错误。
julia> a = Array(Type{S}, 2)
2-element Array{Type{S<:Integer},1}:
#undef
#undef
julia> a[1] = Type{Int32} # or Int32
Type{Int32}
julia> a[2] = Type{Float32} # or Float32
Type{Float32}
julia> a
2-element Array{Type{S<:Integer},1}:
Type{Int32}
Type{Float32}
我会发布一个关于这种奇怪行为的问题。 @Mageek