# Is it possible to express a type relationship between arrays with different numbers of dimensions?

**URL:** <https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 22, 2019, 12:22am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149 "2019-10-22T00:22:10Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 12:22am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/1 "2019-10-22T00:22:10Z")

</div>

What I really want to be able to do is express a type such as:

```julia
struct Foo{T,N}
a::Array{T,N}
b::Array{T,N+1} # doesn't work but I hope it conveys what I want
end

```

The important part for me is that the b field has one more dimension than the a field regardless of how many dimensions a has. I suppose I could add another type parameter for the number of dimensions of b and enforce the relationship in an inner constructor, but that is unwieldy for me, because then any other container or type that uses Foo also has to know about that type parameter. Plus it just feels unsatisfying to have to add an additional type parameter when it’s derived from another. Is there any way to accomplish something like this? As far as I can tell I don’t think there is, but figured I would see if anyone knows about something clever I’m not aware of.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [October 22, 2019, 12:49am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/2 "2019-10-22T00:49:52Z")

</div>

How about `b::Vector{Arrray{T,N}}` It’s slightly different than what you want, but might get the right result.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [October 22, 2019, 1:27am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/3 "2019-10-22T01:27:46Z")

</div>

I’m not that this will fully solve your problem, but you can always omit the `N+1` in the type declaration and enforce it with an inner constructor. As in:

```julia
struct Foo{T,N}
  a::Array{T,N}
  b::Array{T}
end

```

Do you lose anything important that way?

---

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 1:31am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/4 "2019-10-22T01:31:24Z")

</div>

Yeah usually that’s good enough, but in this case I actually do need the memory layout of the higher dimensional array.

---

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 1:34am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/5 "2019-10-22T01:34:28Z")

</div>

That does technically work I guess, but it won’t be type stable which is unfortunate.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 22, 2019, 2:36am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/6 "2019-10-22T02:36:03Z")

</div>

The standard solution here is to write

```julia
struct Foo{T,N,M}
    a::Array{T,N}
    b::Array{T,M}
end

```

and then check in the constructor that `M == N+1`.

---

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 3:15am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/7 "2019-10-22T03:15:41Z")

</div>

Okay, that’s what I thought I had to do. Do you think there is any possibility that there will ever be support for more expressiveness with value types? It seems that at the moment basically every restriction one might want to assert on them has to be handled outside of the type domain: either in inner constructors for structs, or in the body of a function for function arguments. From what I have been able to find it seems that even restricting N to be an Int value has to be done in the constructor. It seems to me that it would be reasonable for values to retain some of their basic relationships to one another even when they are being used as types.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 22, 2019, 3:21am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/8 "2019-10-22T03:21:15Z")

</div>

Possibly. It’s a tricky language design problem though. There’s an issue about it somewhere on GitHub. Something about delayed evaluation of types in struct declarations.

---

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 4:35am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/9 "2019-10-22T04:35:52Z")

</div>

Well that led me down a rabbit hole. Things along this line seem to have come up a bunch of times. I think you’re referring to [https://github.com/JuliaLang/julia/issues/18466](https://github.com/JuliaLang/julia/issues/18466).

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 22, 2019, 4:59am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/10 "2019-10-22T04:59:55Z")

</div>

> [@Oscar\_Smith](#):
>
> `b::Vector{Arrray{T,N}}`

Isn’t this type piracy?

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 22, 2019, 5:20am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/11 "2019-10-22T05:20:10Z")

</div>

> [@DNF](#):
>
> Isn’t this type piracy?

Why would you think it is?

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [October 22, 2019, 5:26am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/12 "2019-10-22T05:26:43Z")

</div>

Well, the spelling, for one thing!

---

<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:** [October 22, 2019, 5:54am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/13 "2019-10-22T05:54:34Z")

</div>

> [@bcmichael](#):
>
> It seems that at the moment basically every restriction one might want to assert on them has to be handled outside of the type domain: either in inner constructors for structs, or in the body of a function for function arguments.

Yes, because that’s the only place where it can possibly matter. For existing objects which are of a parametrized type, the compiler does not need to care about these restrictions.

The constructor is the right place to verify these restrictions, or compute extra types. This design is elegant because it does not require a special syntax for restrictions on types, but subsumes them under all calculations and restrictions the type needs.

This is such a common question that there should be a FAQ entry about it — I will write one today.

---

<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:** [October 22, 2019, 11:30am UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/14 "2019-10-22T11:30:40Z")

</div>

There’s also [GitHub - vtjnash/ComputedFieldTypes.jl: Build types in Julia where some fields have computed types](https://github.com/vtjnash/ComputedFieldTypes.jl) . It doesn’t actually change the fact that your type will have a parameter for N and a parameter for N + 1, but it at least lets you avoid having to write out that parameter most of the time.

---

<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:** [October 22, 2019, 1:28pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/15 "2019-10-22T13:28:02Z")

</div>

PR for FAQ:

[https://github.com/JuliaLang/julia/pull/33631](https://github.com/JuliaLang/julia/pull/33631)

---

<div class="post-metadata">

**Author:** ![abraunst](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraunst/32/6880_2.png) [@abraunst](https://discourse.julialang.org/u/abraunst)\
**Post date:** [October 22, 2019, 1:35pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/16 "2019-10-22T13:35:02Z")

</div>

Aye!

---

<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:** [October 22, 2019, 1:56pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/17 "2019-10-22T13:56:11Z")

</div>

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

I helped bring this package up to date for Julia v1.0 a while back, I use it in some of my packages for the same purpose as the OP asks about

---

<div class="post-metadata">

**Author:** ![tkluck](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkluck/32/15769_2.png) [@tkluck](https://discourse.julialang.org/u/tkluck)\
**Post date:** [October 22, 2019, 4:07pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/18 "2019-10-22T16:07:00Z")

</div>

> [@DNF](#):
>
> Isn’t this type piracy?

Thank you for making my day 😂😂

---

<div class="post-metadata">

**Author:** ![bcmichael](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bcmichael/32/10003_2.png) [@bcmichael](https://discourse.julialang.org/u/bcmichael)\
**Post date:** [October 22, 2019, 4:09pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/19 "2019-10-22T16:09:39Z")

</div>

I’m not convinced it’s terribly elegant. If I want to restrict T to be some sort of Float I write `Foo{T<:AbstractFloat,N}`. That sort of restriction is expressed in the type domain via a type hierarchy. If I want to restrict N to be a particular sort of value type I have to check that restraint myself in a constructor.

They are both restrictions on what sorts of types I can use here, but only one of them can be expressed in the type domain. I can see restrictions on what sort of types these parameters can be by looking at the first line of a struct definition unless I have value types. Julia enforces those restrictions on other types, but for value types I have to enforce those restrictions manually in my code. That doesn’t feel elegant to me.

---

<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:** [October 22, 2019, 4:42pm UTC](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149/20 "2019-10-22T16:42:14Z")

</div>

> [@bcmichael](#):
>
> They are both restrictions on what sorts of types I can use here, but only one of them can be expressed in the type domain.

Subtype relation is special because it is fundamental to a lot of things, most importantly [dispatch](https://docs.julialang.org/en/v1/manual/methods/).

> [@bcmichael](#):
>
> Julia enforces those restrictions on other types, but for value types I have to enforce those restrictions manually in my code.

All kinds of restrictions can be enforced in Julia, it’s just that subtypes have a special syntax. You could do

```julia
struct Foo{T}
    x::T
    function Foo(x::T) where T
        if !(T <: AbstractFloat)
            throw(ArgumentError("look, I really need a float here and $T isn't one"))
        end
        new{T}(x)
    end
end

```

and get pretty much the same behavior as

```julia
struct Foo{T<:AbstractFloat}
    x::T 
end

```

just without some bells and whistles.

> [@bcmichael](#):
>
> That doesn’t feel elegant to me.

Elegance is of course always a subjective term for programming language design. Personally, I find the current setup elegant because of _parsimony_: no extra syntax needs to be introduced, and checking these kind of restrictions is pretty much orthogonal to everything else that happens to instances of this type after construction.

Eg consider a hypothetical

```julia
struct Foo{T,N}
    A::Array{T,N}
    B::Array{T,N+1}
end

```

Suppose I want to retrieve the computed type parameter, without hardcoding the actual computation in my code, for which there is a [very standard pattern](https://docs.julialang.org/en/v1/manual/methods/#Extracting-the-type-parameter-from-a-super-type-1) with explicit parameters. Should we introduce special syntax for this too?

Or consider relations between parameters which you can test for, but not compute (because the relation is not a function, or it is expensive/nontrivial to invert). Instead of

```julia
struct Foo{T,S}
    a::T
    b::S
    function Foo(a::T, b::S) where {T,S}
        check_Foo_types(T, S) || error("baaad types")
        new{T,S}(a, b)
    end 
end

```

you would need to introduce a syntax to specify `check_Foo_types` somewhere, and still use the constructor for other checks.

[Next page](https://discourse.julialang.org/t/is-it-possible-to-express-a-type-relationship-between-arrays-with-different-numbers-of-dimensions/30149.md?page=2)
