Types 类型定义:应为UnionAll,获得TypeVar

Types 类型定义:应为UnionAll,获得TypeVar,types,julia,Types,Julia,在v0.6的Julia手册中,我发现以下内容: abstract type Pointy{T} end struct Point{T} <: Pointy{T} x::T y::T end 有什么不对,我如何才能实现我真正想要的,即指定V尝试以下方法: julia> abstract type Foo{T} end julia> struct Bar{T<:AbstractFloat,V<:AbstractVector{T}} <: Foo

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

abstract type Pointy{T} end
struct Point{T} <: Pointy{T}
    x::T
    y::T
end
有什么不对,我如何才能实现我真正想要的,即指定
V尝试以下方法:

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
julia>抽象类型Foo{T}end
julia>structbar{tbar(rand(Int,3))
ERROR:TypeError:Bar:T中,预期的T另一个选项(让它与@tholy的答案同时工作,并使用与V“include”参数F相同的方法)。为了让它正常工作,应该添加一个外部构造函数,就像@tholy的答案一样(可能这有点多余,但它使用
where
语法)


根据@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
抽象类型Foo{V}end
结构条{V条(2:5)
错误:MethodError:无法将UnitRange{Int64}类型的对象“转换”为Bar类型的对象
我喜欢这一点,因为它看起来更简单,默认构造函数直接工作,并且我没有得到浮点类型变量的“加倍”,即,
Bar{Array{Float64,1}
而不是
Bar{Float64,Array{Float64,1}


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

对,这也有效。解决方案之间的区别在于,您的版本使用构造函数对参数强制约束,而我的版本在类型中强制约束本身。关于我问题的标题:“预期的UnionAll,得到了TypeVar”。你知道这意味着什么吗?不是类型系统的专家,但是
V{F}
是不允许的。
V
F
是类型变量(即参数)解析器需要的不是
V
而是一个
UnionAll
,它是一个类型集合,比如
Array
Vector
。UnionAll的名称
UnionAll
来自表示所有数组{T,N}类型的并集的数组,或者在
where
语法:
Array{T,N}where{T,N}
。具体来说,REPL中包含以下内容:
isa(Array,UnionAll)=true
Array==(Array{T,N}其中{T,N})=true
。如果有很好的查找引用,请将其添加到注释中(或者我会这样做,或者其他人会这样做)太好了!这很有效。你知道我的第一种方法有什么问题吗?我本想在它上面的地方撒一些
,但我不知道该放在哪里。在这种情况下,构造函数应该是内部构造函数吗?啊,我想Dan Getz版本就是这样做的
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
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.
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