# Type parameter transformation, StaticArray with blade indexing

**URL:** <https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371>\
**Category:** General Usage\
**Tags:** question, array, type, parametric-types\
**Created:** [December 6, 2018, 12:24pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371 "2018-12-06T12:24:41Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 6, 2018, 12:24pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/1 "2018-12-06T12:24:41Z")

</div>

My goal is to create a new type, let’s say `MultiVector` which contains an `MVector{2^N,T}` with `2^N` elements, but I am going to define an unusual type of indexing on `MultiVector` using multivector blades.

With standard arrays, this would look like this

```plaintext
mutable struct MultiVector{T}
    N::UInt8
    v::Vector{T}
end

function Base.getindex(m::MultiVector, i::Int) 
    0 <= i <= m.N || throw(BoundsError(m, i))
    r = sum([binomial(Int(m.N),k) for k ∈ 0:i-1])
    return @view m.v[r+1:r+binomial(Int(m.N),i)]
end

```

with the expected behavior like this

```plaintext
julia> g = MultiVector{Int}(2,[3,4,5,6])
MultiVector{Int64}(0x02, [3, 4, 5, 6])

julia> g[0]
1-element view(::Array{Int64,1}, 1:1) with eltype Int64:
 3

julia> g[1]
2-element view(::Array{Int64,1}, 2:3) with eltype Int64:
 4
 5

julia> g[2]
1-element view(::Array{Int64,1}, 4:4) with eltype Int64:
 6

```

However, now I would like to use `StaticArrays` instead of the standard `Array`, so I could do

```plaintext
mutable struct MultiVector
    N::UInt8
    v::MVector
end

```

However, what if I also want to include the parametric type `T` and also specify the size `2^N`, since I am going to be dealing with `MVector{2^N,T}` essentially. Note that the behavior of `MultiVector` is going to be different because the indexing is based on a completely different concept.

This is going to be part of my `Multivectors` package

> **[GitHub - chakravala/Grassmann.jl: ⟨Leibniz-Grassmann-Clifford⟩ multilinear...](https://github.com/chakravala/Grassmann.jl)**
>
> ⟨Leibniz-Grassmann-Clifford⟩ multilinear differential geometric algebra - GitHub - chakravala/Grassmann.jl: ⟨Leibniz-Grassmann-Clifford⟩ multilinear differential geometric algebra

So basically this is a question about parametric types, what is the best way to specify `T` and `N` in the type?

---

<div class="post-metadata">

**Author:** ![sairus7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sairus7/32/10816_2.png) [@sairus7](https://discourse.julialang.org/u/sairus7)\
**Post date:** [December 6, 2018, 12:35pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/2 "2018-12-06T12:35:54Z")

</div>

See how it is done in [OffsetArrays.jl](https://github.com/JuliaArrays/OffsetArrays.jl/blob/master/src/OffsetArrays.jl)

Also, I have asked similar question for custom array types here:

> [@Recipe for custom array types with metadata bound to it](https://discourse.julialang.org/t/recipe-for-custom-array-types-with-meta-data-bound-to-it/18370):
>
> I want to implement custom array type with some additional fields to store useful metadata information bound to that array. But, similar to [OffsetArrays.jl](https://github.com/JuliaArrays/OffsetArrays.jl), I want to implement it for any AbstractArray subtype (simple array, [AxisArray](https://github.com/JuliaArrays/AxisArrays.jl), [StructArray](https://github.com/piever/StructArrays.jl), [CircularBuffer](https://github.com/JuliaCollections/DataStructures.jl/blob/master/src/circular_buffer.jl), etc.). To do that, I should write something like OffsetArray [source](https://github.com/JuliaArrays/OffsetArrays.jl/blob/master/src/OffsetArrays.jl): mutable struct MyArray{T,N,AA\<:AbstractArray} \<: AbstractArray{T,N} array::AA useful\_data1::Int64 useful\_data2::String # and maybe another useful da…

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 6, 2018, 12:56pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/3 "2018-12-06T12:56:28Z")

</div>

> [@sairus7](#):
>
> Also, I have asked similar question for custom array types here:

Alright, that is somewhat useful, but it doesn’t work the way I want. This is valid,

```Julia
julia> mutable struct MyArray{T,N,MV<:MVector{N,T}} <: AbstractArray{T,N}
           v::MV
       end

julia> MyArray{Int,3}
MyArray{Int64,3,MV} where MV<:MArray{Tuple{3},Int64,1,3}

```

However, what I need is an `MVector` with `2^N` elements, which is problematic

```Julia
julia> mutable struct MyArray{T,N,MV<:MVector{2^N,T}} <: AbstractArray{T,N}
           v::MV
       end
ERROR: MethodError: no method matching ^(::Int64, ::TypeVar)

```

which is not valid because `2^N` is a `Type` calculation.

Is it necessary to define a method on `^(Int64, ::TypeVar)` to solve this?

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 6, 2018, 7:01pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/4 "2018-12-06T19:01:03Z")

</div>

Perhaps someone like @jeff.bezanson could comment on whether it is possible with Julia to compute on numerical type variables, such as in the situation where the parameter `N` translates to a parameter `2^N` in one of the fields of the parametric type

```nohighlight
MyArray{T,N,MV<:MVector{2^N,T}} <: AbstractArray{T,N}

```

What I would like is for `N` to be a parameter for a type which contains another parametric type having `2^N` as its parameter, dependent on the `N` parameter of the container parametric type.

So the parameter of the type contained within a parametric type is a transformation of the container’s parametric type, `N -> 2^N` is the type parameter transformation. Is such a thing possible with Julia?

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 8, 2018, 8:16pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/5 "2018-12-08T20:16:50Z")

</div>

So it’s not possible to do anything like this with parametric type variables in Julia? Is it a fundamental limitation with the language, or is it just a feature that’s not implemented yet?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 8, 2018, 8:23pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/6 "2018-12-08T20:23:46Z")

</div>

I think you’re essentially looking for [https://github.com/JuliaLang/julia/issues/18466](https://github.com/JuliaLang/julia/issues/18466)

So no, this isn’t currently possible in Julia. ComputedFieldTypes.jl can make your life a bit easier, but otherwise the easiest thing to do is something like:

```julia
julia> struct MyArray{T, N, MV <: (MVector{N2, T} where N2)}
       end

```

or:

```julia
julia> struct MyArray{T, N, N2, MV <: MVector{N2, T}}
       end

```

(the only difference is whether you want to expose `N2` as its own type parameter).

You can enforce the invariant that `MV` has `N^2` dimensions inside the inner constructor. This is, admittedly, a bit less convenient, but it should perform perfectly well.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 8, 2018, 8:39pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/7 "2018-12-08T20:39:35Z")

</div>

Thanks. How does the constructor work for your first option?

```nohighlight
julia> struct MultiVector{T, MV <: (MVector{N, T} where N)}
           n::UInt8
           v::MV
       end

julia> MultiVector{Int}(0x2,MVector(3,4,5,6))
ERROR: MethodError: no method matching MultiVector{Int64,MV} where MV<:(MArray{Tuple{N},Int64,1,N} where N)(::UInt8, ::MArray{Tuple{4},Int64,1,4})
Stacktrace:
 [1] top-level scope at none:0

julia> methods(MultiVector)
# 1 method for generic function "(::Type)":
[1] (::Type{MultiVector})(n::UInt8, v::MV) where {T, MV<:(MArray{Tuple{N},T,1,N} where N)} in Main at REPL[14]:2

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [December 8, 2018, 8:47pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/8 "2018-12-08T20:47:23Z")

</div>

You can just define some helpful outer constructors:

```julia
julia> MultiVector{T}(n::T, mv::MV) where {T, N, MV <: MVector{N, T}} = MultiVector{T, MV}(n, mv)

julia> MultiVector{Int}(1, MVector(1, 2))
MultiVector{Int64,MArray{Tuple{2},Int64,1,2}}(0x01, [1, 2])

```

```julia
julia> MultiVector(n::T, mv::MV) where {T, N, MV <: MVector{N, T}} = MultiVector{T, MV}(n, mv)

julia> MultiVector{Int}(1, MVector(1, 2))
MultiVector{Int64,MArray{Tuple{2},Int64,1,2}}(0x01, [1, 2])

```

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [December 8, 2018, 10:29pm UTC](https://discourse.julialang.org/t/type-parameter-transformation-staticarray-with-blade-indexing/18371/9 "2018-12-08T22:29:10Z")

</div>

By the way, I updated the `ComputedFieldTypes` repository to Julia 1.0 on my fork

[https://github.com/vtjnash/ComputedFieldTypes.jl/pull/4](https://github.com/vtjnash/ComputedFieldTypes.jl/pull/4)

Using that, this is working

```nohighlight
julia> using ComputedFieldTypes, StaticArrays

julia> @computed mutable struct MultiVector{T,N}
           v::MVector{2^N,T}
       end
fulltype (generic function with 2 methods)

julia> MultiVector{Int,2}(MVector(1,2,3,4))
MultiVector{Int64,2,4}([1, 2, 3, 4])

```
