# Clarification on usage for non-type type parameters

**URL:** <https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [April 20, 2021, 2:39pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669 "2021-04-20T14:39:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Samuele-Colombo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuele-colombo/32/23281_2.png) [@Samuele-Colombo](https://discourse.julialang.org/u/Samuele-Colombo)\
**Post date:** [April 20, 2021, 2:39pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/1 "2021-04-20T14:39:07Z")

</div>

Hi, I was trying to define an `abstract type` which I would like to be subtype of `FieldVector{N,T}`, from the package `StaticArrays`, where `N` must be `Unsigned`. If it were simply a case like the following

```julia
abstract type MyType{N, T} <: FieldVector{N, T} end

```

everything is ok, it precompiles an executes beautifully. The problem arises when I do want to manipulate `N` before passing it to `FieldVector`. For example if I were to try and write

```julia
abstract type MyType{N, T} <: FieldVector{2N, T} end

```

the resulting error would state

```julia
ERROR: MethodError: no method matching *(::Int64, ::TypeVar)
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
  *(::T, ::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} at int.jl:88
  *(::Union{Int16, Int32, Int64, Int8}, ::BigInt) at gmp.jl:541
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[4]:1

```

which clearly indicates that, by default, any type parameter is interpretered as a `TypeVar` instance which, obviously, has no multiplication operation defined. So I try and specify to the compiler that `N` is of type `Unsigned` using the same syntax I use for the functions

```julia
abstract type MyType{N::Unsigned, T} <: FieldVector{2N, T} end

```

but this raises the cryptic error

```julia
ERROR: syntax: invalid variable expression in "where" around REPL[5]:1
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

```

So my question is: **how do I tell the compiler that `N` is a non-type type parameter?**

I tried to look for examples of this behavior online and in the source code of some libraries but I found no solution in my search.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 20, 2021, 3:27pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/2 "2021-04-20T15:27:16Z")

</div>

> [@Samuele-Colombo](#):
>
> The problem arises when I do want to manipulate `N` before passing it to `FieldVector` .

Could you explain in which situation you would do that?

> [@Samuele-Colombo](#):
>
> `abstract type MyType{N, T} <: FieldVector{2N, T} end`

this wouldn’t change anything for type-inference except the `N` of the custom type being another number than that of the FieldVector, but if the number of fields is smaller that subtyping would break everything that was implemented for `FieldVector`:

```julia
julia> struct V{N,T} <: FieldVector{N,T}
         x
         y
       end

julia> x = ones(V{3,Float64})
ERROR: StackOverflowError:

```

So maybe if you explain what exactly what you want to achieve with that subtyping a better solution appears.

---

<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:** [April 20, 2021, 3:45pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/3 "2021-04-20T15:45:13Z")

</div>

> [@Samuele-Colombo](#):
>
> how do I tell the compiler that `N` is a non-type type parameter?

There’s currently no way to do this. The typical approach is to introduce a new type parameter and then enforce the invariant in your inner constructor:

```julia
struct MyType{N, T, N2}
  ...
  function MyType{N, T}(...)
    new{N, T, 2 * N}(...)
  end

  # or, alternatively
  function MyType{N, T, N2}(...)
    @assert N2 == 2 * N
    ...
  end
end

```

[GitHub - vtjnash/ComputedFieldTypes.jl: Build types in Julia where some fields have computed types](https://github.com/vtjnash/ComputedFieldTypes.jl) can help automate some of this for you. Unfortunately, abstract types do not have inner constructors, so I’m not sure how to apply this suggestion to the abstract `MyType`, except to pass the work of checking `N2` on to whatever concrete types end up inheriting from `MyType`.

---

<div class="post-metadata">

**Author:** ![Samuele-Colombo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuele-colombo/32/23281_2.png) [@Samuele-Colombo](https://discourse.julialang.org/u/Samuele-Colombo)\
**Post date:** [April 20, 2021, 5:05pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/4 "2021-04-20T17:05:32Z")

</div>

> [@rdeits](#):
>
> There’s currently no way to do this. The typical approach is to introduce a new type parameter and then enforce the invariant in your inner constructor
> 
> ```julia
> 
> ```

This is unfortunate, your solution is interesting, I’ll try and implement it, but delegating the work of an abstraction to its concrete types removes the elegancy of the usual notation. I hope a language level workaround will be found in future versions of Julia. Thanks!

---

<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:** [April 20, 2021, 5:23pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/5 "2021-04-20T17:23:55Z")

</div>

Yeah, I agree it’s pretty awkward.

You could consider changing your abstraction such that the `N` in `MyType` is equal to the `N` in the `FieldVector` (twice your current value). Or perhaps you can treat your data as a pair of `N`-element vectors instead of a single `2N` element vector. Or maybe there’s some other more convenient way to do whatever it is that you’re actually hoping to accomplish.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 20, 2021, 6:10pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/6 "2021-04-20T18:10:54Z")

</div>

> [@rdeits](#):
>
> Or perhaps you can treat your data as a pair of `N` -element vectors instead of a single `2N` element vector.

For the particular case of `FieldVector` from StaticArrays, what that could be useful for? (sincere doubt, maybe I am missing something). FieldVector is thought to provide a convenient way to define, for example:

```julia
struct Vec{3,T} <: FieldVector{3,T}
  x::T 
  y::T 
  z::T 
end

```

such that all algebra operations and methods that are defined for static vectors will work for `Vec`. If one defines `Vec` with a different inner structure than that (3 fields of the same number type) all those methods will break. Is there any other utility for defining a subtype that does not follow the strict pattern of `FieldVector{N,T}`?

---

<div class="post-metadata">

**Author:** ![Samuele-Colombo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuele-colombo/32/23281_2.png) [@Samuele-Colombo](https://discourse.julialang.org/u/Samuele-Colombo)\
**Post date:** [April 20, 2021, 9:40pm UTC](https://discourse.julialang.org/t/clarification-on-usage-for-non-type-type-parameters/59669/7 "2021-04-20T21:40:45Z")

</div>

> [@rdeits](#):
>
> Or maybe there’s some other more convenient way to do whatever it is that you’re actually hoping to accomplish.

The case I presented in the original post was greatly simplified to not divert attention from the core issue.

What I am actually trying to accomplish is a basic implementation of [Geometric Algebra](https://en.wikipedia.org/wiki/Geometric_algebra), in particular of the [multivector](https://en.wikipedia.org/wiki/Multivector).

A multivector in `N` dimensions has `sum(binomial(N, k) for k ∈ 0:N)` values associated (in 3D they are 8: a scalar, three vector components, three pseudovector components and a pseudoscalar).

Since i could not find a way to declare a `MultiVector{N, T}` type on the fly at runtime (I might ask another question for that), I thought to manually implement just the `N = 1, 2, 3` cases since they are the most used. An example in 3D would be

```julia
struct MultiVector3D{T} <: MultiVector{3, T}
    # scalar
    s::T 
    # vector components 
    x̂::T
    ŷ::T
    ẑ::T
    # pseudovector components
    x̂ŷ::T
    x̂ẑ::T
    ŷẑ::T
    # pseudoscalar
    x̂ŷẑ::T
end

```

These concrete types would be subtypes of an abstract type defined as

```julia
nfields(n::Unsigned) = sum(binomial(n, k) for k ∈ 0:n)
abstract type MultiVector{N, T} <: FieldVector{nfields(N), T}

```

so that common behavior could be defined once and the code is cleaner and more organized.

I don’t know if maybe there is a lampant workaround to my specific problem that I haven’t thought about.
