# Require all arrays in struct to be of same kind and type

**URL:** <https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237>\
**Category:** General Usage\
**Created:** [April 8, 2022, 7:55pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237 "2022-04-08T19:55:30Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [April 8, 2022, 7:55pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/1 "2022-04-08T19:55:30Z")

</div>

I have a struct that I would like to consist of only `Array` or `CuArray`, but I would like a mix of different kinds to throw. I can enforce uniform types by using the `{T}`, but how do I define my struct to make the `vel_mix` construction throw an error?

```julia
using CUDA

struct Velocity{T}
    u::AbstractArray{T, 2}
    v::AbstractArray{T, 2}
end

u = zeros(3, 3); v = zeros(3, 3)

vel_cpu = Velocity(u, v) # OK
vel_gpu = Velocity(CuArray(u), CuArray(v)) # OK
vel_mix = Velocity(CuArray(u), v) # I would like this one to throw.

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 8, 2022, 8:05pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/2 "2022-04-08T20:05:37Z")

</div>

```julia
julia> struct Velocity{T, U<:AbstractArray{T}}
           u::U
           v::U
       end

julia> Velocity([1,2], 1:2)
ERROR: MethodError: no method matching Velocity(::Vector{Int64}, ::UnitRange{Int64})
Closest candidates are:
  Velocity(::U, ::U) where {T, U<:(AbstractArray{T})} at REPL[1]:2
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

julia> Velocity([1,2], [1,2])
Velocity{Int64, Vector{Int64}}([1, 2], [1, 2])

julia> Velocity(1:2, 1:2)
Velocity{Int64, UnitRange{Int64}}(1:2, 1:2)

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [April 8, 2022, 8:09pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/3 "2022-04-08T20:09:29Z")

</div>

I think you can even drop the first type parameter:

> **click me for code**
>
> ```julia
> julia> struct Velocity{U<:AbstractArray}
> u::U
> v::U
> end
> 
> julia> Velocity(1:2, 1.0:2.0)
> ERROR: MethodError: no method matching Velocity(::UnitRange{Int64}, ::StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64})
> Closest candidates are:
> Velocity(::U, ::U) where U<:AbstractArray at REPL[1]:2
> Stacktrace:
> [1] top-level scope
> @ REPL[2]:1
> 
> julia> Velocity(1:2, [1,2])
> ERROR: MethodError: no method matching Velocity(::UnitRange{Int64}, ::Vector{Int64})
> Closest candidates are:
> Velocity(::U, ::U) where U<:AbstractArray at REPL[1]:2
> Stacktrace:
> [1] top-level scope
> @ REPL[3]:1
> 
> julia> Velocity(1:2, 1:2)
> Velocity{UnitRange{Int64}}(1:2, 1:2)
> 
> julia> Velocity([1,2], [1,2])
> Velocity{Vector{Int64}}([1, 2], [1, 2])
> 
> julia> Velocity([1,2], [1.0,2.0])
> ERROR: MethodError: no method matching Velocity(::Vector{Int64}, ::Vector{Float64})
> Closest candidates are:
> Velocity(::U, ::U) where U<:AbstractArray at REPL[1]:2
> Stacktrace:
> [1] top-level scope
> @ REPL[6]:1
> 
> ```

though you are going to need at least `U <: AbstractArray{T} where T` if you want to use `T` as well for dispatch or use it in the struct.

---

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [April 8, 2022, 8:17pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/4 "2022-04-08T20:17:34Z")

</div>

And what if I wanted:

```julia
struct Velocity{T}
    u::AbstractArray{T, 2}
    v::AbstractArray{T, 2}
    z::AbstractArray{T, 1}
end

```

where the last element must be of the same kind and type, but has one dimension less?

---

<div class="post-metadata">

**Author:** ![Jordan\_Cluts](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jordan_cluts/32/13753_2.png) [@Jordan\_Cluts](https://discourse.julialang.org/u/Jordan_Cluts)\
**Post date:** [April 8, 2022, 8:36pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/5 "2022-04-08T20:36:03Z")

</div>

I may be wrong but I think you’ll need to use a constructor to enforce the dimensions. I don’t think you can express the relationship of “one dimension less” (because you can’t do math on the type) in the type system (but please someone prove me wrong if it is possible).

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 8, 2022, 9:15pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/6 "2022-04-08T21:15:25Z")

</div>

> [@Chiil](#):
>
> And what if I wanted:
> 
> ```julia
> struct Velocity{T}
> u::AbstractArray{T, 2}
> 
> ```

You probably don’t want this, because then the `u` [field is abstractly typed](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-type).

Better to have something like:

```julia
struct Velocity{A<:AbstractMatrix}
    u::A
    v::A
end

```

---

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [April 9, 2022, 6:51pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/7 "2022-04-09T18:51:46Z")

</div>

My question wasn’t well formulated. What I meant to ask was: what if I mix different dimension sizes, can I define the struct such that _all_ arrays are of the same kind, irrespective of their nmber of dimensions, or do I need a constructor for that?

For instance

```julia
struct Velocity{T, U2 <: AbstractArray{T, 2}, U1 <: AbstractArray{T, 1}}
    u::U2
    v::U2
    z::U1
end

```

would not solve it, because it allows `U1` to be an `Array` and `U2` a `CuArray`.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [April 9, 2022, 6:56pm UTC](https://discourse.julialang.org/t/require-all-arrays-in-struct-to-be-of-same-kind-and-type/79237/8 "2022-04-09T18:56:58Z")

</div>

> [@Chiil](#):
>
> what if I mix different dimension sizes, can I define the struct such that _all_ arrays are of the same kind

I don’t think so.
