类型定义:期望UnionAll,得到TypeVar

时间:2017-05-25 10:38:00

标签: types julia

在v0.6的Julia手册中,我找到以下内容:

abstract type Pointy{T} end
struct Point{T} <: Pointy{T}
    x::T
    y::T
end

这很好用,我认为还应该如下:

abstract type Foo{V, F} end
struct Bar{V, F} <: Foo{V, F}
    x::V{F}
end

Bar的定义给出了以下错误

ERROR: TypeError: Type{...} expression: expected UnionAll, got TypeVar

有什么问题,我怎样才能实现我真正想要的,即指定V<:AbstractVectorF<:AbstractFloat

3 个答案:

答案 0 :(得分:3)

试试这个:

julia> abstract type Foo{T} end

julia> struct Bar{T<:AbstractFloat,V<:AbstractVector{T}} <: Foo{T}
           x::V
       end

julia> Bar{T}(v::AbstractVector{T}) = Bar{T,typeof(v)}(v) # constructor
Bar

julia> Bar(rand(3))
Bar{Float64,Array{Float64,1}}([0.387467, 0.535419, 0.240748])

julia> Bar(rand(Int, 3))
ERROR: TypeError: Bar: in T, expected T<:AbstractFloat, got Type{Int64}
Stacktrace:
 [1] Bar(::Array{Int64,1}) at ./REPL[4]:1

答案 1 :(得分:2)

另一种选择(让它与@ tholy的答案同时工作并使用相同的路线来获得V&#34;包括&#34;参数F)。为了让它工作得很好,应该添加一个外部构造函数,比如@ tholy的答案(可能这有点多余,但它使用where语法)

struct Bar{V, F} <: Foo{V,F}
    x::V
    Bar{V,F}(x::V) where {F, V<:AbstractVector{F}} = new(x)
end

这就是这样的:

julia> Bar{Vector{Int},Int}([1,2,3])
Bar{Array{Int64,1},Int64}([1, 2, 3])

julia> Bar{Vector{Int},Float64}([1,2,3])
ERROR: MethodError: Cannot `convert` an object of type Array{Int64,1} to an object of type Bar{Array{Int64,1},Float64}
This may have arisen from a call to the constructor Bar{Array{Int64,1},Float64}(...),
since type constructors fall back to convert methods.

答案 2 :(得分:1)

根据@tholy和@DanGetz的答案,我搞砸了一下,想出了一个我喜欢的答案:

abstract type Foo{V} end
struct Bar{V <: AbstractVector{<:AbstractFloat}} <: Foo{V}
    x::V
end

julia> Bar(rand(5))
Bar{Array{Float64,1}}([0.722314, 0.159418, 0.13561, 0.288794, 0.347009])

julia> Bar(2.0:5.0)
Bar{StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}}(2.0:1.0:5.0)

julia> Bar(2:5)
ERROR: MethodError: Cannot `convert` an object of type UnitRange{Int64} to an object of type Bar

我喜欢这个,因为它似乎更简单,默认构造函数直接工作,而且我没有得到浮点类型变量“加倍”,即Bar{Array{Float64,1}}而不是Bar{Float64,Array{Float64,1}}

不确定此版本是否有任何缺点。另外,我仍然不明白为什么我的一些努力会起作用,而有些则因语法或其他错误而失败。