TL;DR: how to define a parametric type where the parameter is another parametric type?
I want to design some algorithms handling point clouds, where each point has some weight. I want to allow for general point clouds as well as point clouds with some structure (say, living on a grid), so I define the abstract type
abstract type AbstractPointCloud{D} end
Then, a struct holding a generic point cloud could be defined as
mutable struct PointCloud{D} <: AbstractPointCloud{D}
weights::Vector{Float64}
positions::Matrix{Float64}
function PointCloud(weights, positions)
D = size(positions, 1)
length(weights) == size(positions, 2) || error("lenghts of weights and positions not matching")
new{D}(weights, positions)
end
end
where weights[i]
encodes the weight of point positions[:,i]
.
So far everything works. But now I want to define another struct that encodes a given point cloud at different resolutions. This could be just a list of the point clouds at those different resolutions, but assume I want to store more info, like for example how to refine one point cloud to another. Then my guess of how to do it is:
mutable struct MultiScalePointCloud{C<:AbstractPointCloud{D}}
clouds::Vector{C}
# plus other info about the point clouds
end
But this throws an error:
UndefVarError: D not defined
Stacktrace:
[1] top-level scope
@ In[3]:1
[2] eval
@ ./boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
@ Base ./loading.jl:1094
If I try to leave D
a free parameter:
mutable struct MultiScalePointCloud{C<:AbstractPointCloud{D}} where D
clouds::Vector{C}
# plus other info about the point clouds
end
I get another error:
syntax: invalid type signature around In[4]:1
Stacktrace:
[1] top-level scope
@ In[4]:1
[2] eval
@ ./boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
@ Base ./loading.jl:1094
So, how would one overcome this? Thanks!