# Extending AbstractArray while wrapping any AbstractArray

**URL:** <https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310>\
**Category:** Internals & Design\
**Tags:** question, parametric-types\
**Created:** [July 11, 2018, 7:32am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310 "2018-07-11T07:32:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [July 11, 2018, 7:32am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/1 "2018-07-11T07:32:38Z")

</div>

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`:

```julia
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`?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 11, 2018, 7:53am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/2 "2018-07-11T07:53:29Z")

</div>

Perhaps

```julia
struct Layer2{T, S <: AbstractMatrix{T}} <: AbstractLayer{T}
    data::S
    other_field::Int
end

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [July 11, 2018, 12:46pm UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/3 "2018-07-11T12:46:09Z")

</div>

> [@Tamas\_Papp](#):
>
> struct Layer2{T, S \<: AbstractMatrix{T}} \<: AbstractLayer{T} data::S other\_field::Int end

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:

```julia
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

```

```julia

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [July 12, 2018, 6:25am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/4 "2018-07-12T06:25:00Z")

</div>

For future reference this works:

```julia
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.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [July 12, 2018, 9:02am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/5 "2018-07-12T09:02:37Z")

</div>

You are hitting [https://github.com/JuliaLang/julia/issues/9441](https://github.com/JuliaLang/julia/issues/9441) (see also [https://github.com/JuliaLang/julia/issues/13297](https://github.com/JuliaLang/julia/issues/13297), [https://github.com/JuliaLang/julia/issues/11597](https://github.com/JuliaLang/julia/issues/11597)). In your example:

```julia
Layer <: AbstractLayerWrapper # false -> thus the dispatch does not work

```

The work-around is to add the type-parameter constraints to the subtypes as well:

```julia
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

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [July 12, 2018, 10:36am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/6 "2018-07-12T10:36:17Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [July 12, 2018, 10:38am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/7 "2018-07-12T10:38:35Z")

</div>

Or is the issue that the subtyping actually wont work?

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [July 12, 2018, 11:27am UTC](https://discourse.julialang.org/t/extending-abstractarray-while-wrapping-any-abstractarray/12310/8 "2018-07-12T11:27:32Z")

</div>

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?
