Proper parametric subtyping of AbstractArray

I ended up banging my head against this yesterday, I guess I’m interested by both the how to do this properly as well as the why did the other ways not work in order to get better at this parametric type business.

Aim: have an object that’s a subtype of AbstractVector which keeps track of two things:

  • a support (vector of, say, symbols) of length c
  • an array of weights of size n x c (e.g. scores returned by a classifier)

so each “element” of the vector corresponds to a pair (support, weights) where support and weights have the same length c.

What I tried to express in a parametric way is that the support and the number of columns of the arrays are tied. So I tried:

julia> struct Foo{W<:AbstractArray{<:Real, C}, S<:NTuple{C,Symbol}} where {C} <: AbstractVector
           weights::W
           support::S
       end
ERROR: syntax: invalid type signature
Stacktrace:
 [1] top-level scope at none:1

crap. (By the way that error message is a bit unhelpful.).

So I tried something simpler to try to build from there:

julia> struct Foo{T, C} <: AbstractVector
           weights::Array{T,C}
           support::NTuple{C,Symbol}
       end
ERROR: invalid subtyping in definition of Foo
Stacktrace:
 [1] top-level scope at none:1

:frowning: after trying many more sillier variants and eventually coming to the conclusion that clearly I didn’t understand what I was doing, I decided to ask for help, so here I am, help!

PS: in the mean time I’m using something less constraining with an internal constructor that checks that dimensions match but it feels unsatisfactory.

1 Like

I am not sure I understood the specs, but I am wondering if you are simply looking for

struct Foo{T,C,W<:AbstractArray{T,C},S<:NTuple{C,Symbol}} <: AbstractVector{T}
    weights::W
    support::S
end

Note

  1. that parametric supertypes need parameters, eg

    struct Bar <: AbstractVector end
    

    will error,

  2. structs cannot have an UnionAll/where clause outside (what would it even mean?), so

    struct Baz{T} where T end
    

    will error.

These two are MWE for your error messages.

You may want to revisit the types chapter of the manual.

2 Likes

Thanks Tamas, so I basically needed to add “C” as a free parameter (as opposed to that ill-placed “where” that you flagged), thanks a lot for that! (and fair enough for the sub typing needing parameter :+1: )

These seem at odds. An Array{T, C} isn’t an NxC array, but a C-dimensional array. It’s a bit unclear to me what you are going for, but are you confusing dimensions with sizes here?

The number of columns of an ordinary Array is not expressed in the type domain, you’ll have to use a different kind of array for that, for example a StaticArray. For ordinary Arrays you’ll have to enforce it in the constructor.

1 Like

Yes I realise that my question was not asked properly but it was the answer I was looking for (I understand that array dimensions are not parametrised, my mistake for trying to write a simplified MWE), I guess what I would probably want is an NTuple of Vectors or indeed a StaticArrays. Thanks!

1 Like