In the Julia manual for v0.6 I find the following:
abstract type Pointy{T} end
struct Point{T} <: Pointy{T}
x::T
y::T
end
This works fine, and I thought the following should as well:
abstract type Foo{V, F} end
struct Bar{V, F} <: Foo{V, F}
x::V{F}
end
The definition of Bar
gives, however, the following error
ERROR: TypeError: Type{...} expression: expected UnionAll, got TypeVar
What is wrong, and how can I achieve what I really want, namely to specify that V<:AbstractVector
and F<:AbstractFloat
?
Try this:
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
Another option (got it to work concurrently with @tholy's answer and uses the same route of having V "include" the parameter F). To get it to work nicely, an external constructor should be added, like @tholy's answer (maybe this was a bit redundant, but it uses the where
syntax)
struct Bar{V, F} <: Foo{V,F}
x::V
Bar{V,F}(x::V) where {F, V<:AbstractVector{F}} = new(x)
end
and this works like so:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With