约束DataType的Vector是特定的抽象类型

时间:2015-10-04 04:09:28

标签: julia

是否可以创建一个函数,它接受::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

谢谢

2 个答案:

答案 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

编辑:

嗯,似乎这个问题并不那么简单。这里的关键点是DataTypeType{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}是不可能的。

  1. DataType没有类型参数。

  2. 以下定义不起作用,这似乎是一个错误。

    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}
    
  3. 我会发布一个关于这种奇怪行为的问题。 @Mageek