This must be fairly simple but I couldn’t find an example. I’m wondering about the standard way to extend AbstractArray while wrapping any other AbstractArray. Say I want to extend AbstractMatrix:
abstract type AbstractLayer{T} <: AbstractMatrix{T} end
struct Layer1{T} <: AbstractLayer{T}
data::AbstractMatrix{T}
end
struct Layer2{T} <: AbstractLayer{T}
data::AbstractMatrix{T}
other_field::Int
end
...
How do I use a parametric type instead of AbstractMatrix?
Thanks! I was hoping to abstract it further so I can write an outer constructor at the AbstractLayer level, so that Layer([1 2;3 4]) works automatically for anything inheriting AbstractLayer. Something like this, but I’m not sure how to get the generic outer constructor working:
abstract type AbstractLayer{T,S <: AbstractMatrix{T}} <: AbstractMatrix{T} end
(::Type{L} where L<:AbstractLayer)(data::S) where S = begin
L{eltype(S),S}(data)
end
struct Layer{T,S} <: AbstractLayer{T,S}
data::S
end
abstract type AbstractLayerWrapper{T, S <: AbstractMatrix{T}} <: AbstractMatrix{T} end
abstract type AbstractLayer{T,S} <: AbstractLayerWrapper{T,S} end
(::Type{F})(data) where F <: AbstractLayer = begin
F{eltype(data),typeof(data)}(data)
end
struct Layer{T,S} <: AbstractLayer{T,S}
data::S
end
But for some reason I don’t understand dispatching on (::Type{F})(data) where F<: AbstractLayerWrapper doesn’t work.
Layer <: AbstractLayerWrapper # false -> thus the dispatch does not work
The work-around is to add the type-parameter constraints to the subtypes as well:
abstract type AbstractLayerWrapper{T, S <: AbstractMatrix{T}} <: AbstractMatrix{T} end
abstract type AbstractLayer{T,S <: AbstractMatrix{T}} <: AbstractLayerWrapper{T,S} end
(::Type{F})(data) where F <: AbstractLayer = begin
F{eltype(data),typeof(data)}(data)
end
struct Layer{T,S <: AbstractMatrix{T}} <: AbstractLayer{T,S}
data::S
end
Layer <: AbstractLayerWrapper # true -> now your dispatch should work
Oh right I thought there was some kind of weirdness happening.
I’m going to leave it as is to reduce boilerplate and complexity… the wrapper type just wont get exported. AbstractLayer is meant to be easily extensible by regular scientists so Layer{T,S} <: AbstractLayer{T,S} is about as weird as I want anything to look!
Maybe just document that S<:AbstractMatrix{T} and check this in your (::Type{F})(data) where F <: AbstractLayer constructor. Then leave all parameter constraints away?