I have a type parameterised by floating point precision, something like this:
struct MyType{T <: AbstractFloat}
x::T
data::Array{T}
end
Note that it’s import that the type of x and the type of the array data match.
And I want this to also work on the GPU, so basically I also want this to be valid:
struct MyType{T <: AbstractFloat}
x::T
data::CuArray{T}
end
My natural attempt to resolve this is to provide an additional type parameter, something like:
struct MyType{T <: AbstractFloat, P <: AbstractArray}
x::T
data::P{T}
end
However, Julia complains TypeError: in Type{...} expression, expected UnionAll, got a value of type TypeVar
.
Two questions:
Why isn’t this valid?
What is the most natural (and simple) way to express this kind of type and constraint?
(Simplified) It doesn’t work because P
could already match a concrete type. For example, P
could be Array{Float64,1}
, so P{T}
is not valid.
Usestruct MyType{T <: AbstractFloat, P <: AbstractArray{T}}
x::T
data::P
end
instead.
Note also that in your original example, data::Array{T}
is not a concrete type (the second type parameter is missing), so this would slow down your code.
goerch
February 1, 2022, 8:13am
3
The following might help:
struct MyType{T <: AbstractFloat, P <: AbstractArray{T}}
x::T
data::P
end
x = MyType(1.0, Vector{Float64}(undef, 1))
println(typeof(x))
y = MyType(1.0, Matrix{Float64}(undef, 1, 1))
println(typeof(y))
z = MyType(1.0, Matrix{Int}(undef, 1, 1))
println(typeof(z))
yielding
MyType{Float64, Vector{Float64}}
MyType{Float64, Matrix{Float64}}
ERROR: LoadError: MethodError: no method matching MyType(::Float64, ::Matrix{Int64})
Thank you! Exactly what I was looking for.