Parametric type which contains the abstract type it subtypes

I’m creating a type that is a matrix with value bounds.

This works:

struct Map{M<:AbstractMatrix{<:Real}}
    data::M
    lb
    ub
end

But I want it to behave like a matrix itself too, so a subtype.

This works:

struct Map{T} <: AbstractMatrix{T}
    data::Matrix{T}
    lb
    ub
end

But this specifies a concrete Matrix inside, which can’t change even if a different form of matrix is passed in. So I’ve tried many variations of where T but they all fail with “T not defined”:

struct Map{M<:AbstractMatrix{T}} <: AbstractMatrix{T} where T<:Real
    data::M
    lb
    ub
end

Is there a way to allow the new type to adapt to any subtype of AbstractMatrix while still subtyping AbstractMatrix? Or is my thought to preserve concrete-type flexibility wrong? I’m trying to get this functionality while avoiding the ambiguity problem discussed in Performance Tips · The Julia Language.

struct Map{T<:Real, M<:AbstractMatrix{T}} <: AbstractMatrix{T}
    data::M
    lb
    ub
end

You might want to give lb and ub a type as well, to avoid a type instability. The default for non-annotated fields in structs is Any after all.

Additionally, this will be helpful:

2 Likes

Perfect! Thanks for your help. So parameters within other parameters need to also be listed as parameters first?

Yes, if you want to use those parameters in your struct as well or otherwise want to introduce a cross-cutting constraint, like the one spanning both the declared supertype and a field (unfortunately).