# Arithmetic for parametric type values in structs e.g., N+1

**URL:** <https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 28, 2024, 11:37pm UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925 "2024-02-28T23:37:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Abhinav\_Bhatia](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abhinav_bhatia/32/18748_2.png) [@Abhinav\_Bhatia](https://discourse.julialang.org/u/Abhinav_Bhatia)\
**Post date:** [February 28, 2024, 11:37pm UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/1 "2024-02-28T23:37:18Z")

</div>

How can I do something like:

```julia
struct Foo{N}
    arr1::Array{Float64, N}
    arr2::Array{Float64, N+1}
end

```

i.e., I want arr2 to be always of 1 higher rank than arr1. How to do this?

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [February 29, 2024, 2:26am UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/2 "2024-02-29T02:26:05Z")

</div>

Maybe there’s a fancier way but this seems to work fine.

```julia
julia> struct Foo{A,B}
           a::A
           b::B
           Foo{A,B}(a,b) where {A,B} = ndims(a)+1 == ndims(b) ? new{A,B}(a,b) : error("wrong dims")
       end

julia> (Foo(a::A,b::B) where {A,B}) = Foo{A,B}(a,b)
Foo

julia> Foo([1], [1;;2])
Foo{Vector{Int64}, Matrix{Int64}}([1], [1 2])

julia> Foo([1], [1])
ERROR: wrong dims

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 29, 2024, 2:44am UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/3 "2024-02-29T02:44:43Z")

</div>

It is impossible for the composite type to do parameter constraints other than `<:` in the implicit `where` clause, you need to enforce it in an inner constructor call like jar1 demonstrated. The reason is that generic functions like `+` can depend on input types and can be changed interactively, so a constraint based on a generic method could also change interactively, but a composite type CANNOT change because of existing instances. That’s also why you need the “redundant” parameter `B==A+1`; after a constraint change, the type system must distinguish previous `Foo{1, 2}` instances from newer `Foo{1, 42}` instances.

The inner constructor should be enough, it is unsafe (in other words, user beware) to bypass inner constructors with `reinterpret` or `@eval @inline outnew(T, args...) = $(Expr(:splatnew, :T, :args)) #:new for an unsplatted number of separate arguments`. I am uncertain if it is hypothetically possible to extend constraints to intrinsic and built-in functions, which I don’t think can change.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [February 29, 2024, 3:12am UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/4 "2024-02-29T03:12:25Z")

</div>

I would do the following.

```julia
julia> struct Foo{N,M}
           arr1::Array{Float64, N}
           arr2::Array{Float64, M}
           Foo{N}(a,b) where N= new{N, N+1}(a,b)
       end

julia> Foo{1}(rand(2), rand(2,3))
Foo{1, 2}([0.9165330134722103, 0.8133055136507046], [0.15120619990261142 0.8543356012671888 0.5239972992036701; 0.12074486400173157 0.6817097391005016 0.3327645622931258])

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [February 29, 2024, 3:21am UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/5 "2024-02-29T03:21:20Z")

</div>

That’s even neater and closer matches the OP, and I’d suggest rounding it out with an outer constructor like jar1 did for convenience:

```julia
julia> Foo(a, b) = Foo{ndims(a)}(a, b)
Foo

julia> Foo(rand(2), rand(2,3))
Foo{1, 2}([0.7928217615317612, 0.27627055084273566], [0.8947120194686449 0.7069448391898014 0.628333742859724; 0.3193547716322238 0.7802926781126777 0.9817486584424423])

```

and incorporating a more descriptive error message in the inner `Foo{N}` than a conversion error in `new`. Note this approach consciously sacrifices a `Foo{N, M}` constructor, so the output of `typeof` can’t instantiate.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [February 29, 2024, 3:37am UTC](https://discourse.julialang.org/t/arithmetic-for-parametric-type-values-in-structs-e-g-n-1/110925/6 "2024-02-29T03:37:47Z")

</div>

> [@Benny](#):
>
> so the output of `typeof` can’t instantiate.

I like [`ConstructionBase.constructorof`](https://juliaobjects.github.io/ConstructionBase.jl/dev/#ConstructionBase.constructorof) for getting constructors instead of `typeof`.
