2017-05-25 38 views
2

在朱莉婭手冊V0.6我覺得以下幾點:類型定義:預計UnionAll,得到TypeVar

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

試試這個:

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 
+0

太棒了!這工作。你知道我的第一種方法有什麼問題嗎?我預計不得不在其上撒上一些「哪裏」,但我無法弄清楚把它們放在哪裏。 – DNF

+0

在這種情況下構造函數應該是內部構造函數嗎? –

+0

啊,我想這是丹Getz版本 –

1

另一種選擇(得到它與@勒託利的答案同時工作,使用具有V的相同路線「包括」參數F)。爲了得到它很好地工作,外部構造應增加,如@勒託利的答案(也許這是一個有點多餘,但它使用的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. 
+1

對,這也適用。解決方案之間的區別在於,您的版本使用*構造函數*來強制對參數進行約束,而我的強制類型本身。 – tholy

+0

關於我的問題的標題:「期待UnionAll,得到TypeVar」。你碰巧知道這意味着什麼? – DNF

+1

不是類型系統的專家,但不允許使用「V {F}」。 'V'和'F'是TypeVars(即參數),而不是'V',解析器想要一個'UnionAll',它是一個類型集合,比如'Array'或'Vector'。名稱「UnionAll」來自表示所有數組{T,N}類型或「where」語法的並集的數組:「Array {T,N},其中{T,N}'。具體來說,下面的代碼保存在REPL中:'isa(Array,UnionAll)== true'和'Array ==(Array {T,N} where {T,N})== true'。如果有很好的查找參考,請將其添加到評論中(或者我會做,或者其他人) –

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 

我喜歡這個,因爲它似乎更簡單,默認CON structor直接工作,並且我沒有得到浮點型typevar的「加倍」,即Bar{Array{Float64,1}}而不是Bar{Float64,Array{Float64,1}}

不知道這個版本是否有什麼缺點。另外,我仍然不明白爲什麼我的一些工作會發揮作用,有些會因語法或其他錯誤而失敗。

相關問題