# Define struct with two fields that have the same abstract type but different specialization

**URL:** <https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945>\
**Category:** General Usage\
**Created:** [July 22, 2025, 3:12pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945 "2025-07-22T15:12:28Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![zsoerenm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zsoerenm/32/664_2.png) [@zsoerenm](https://discourse.julialang.org/u/zsoerenm)\
**Post date:** [July 22, 2025, 3:12pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945/1 "2025-07-22T15:12:28Z")

</div>

Let’s say I want to have a struct with two fields that both are arrays.  
I want both array types to be the same e.g. Array, Array or CuArray, CuArray  
But the specialization should be different like the first one holds float values and the second one integer values.

```julia
struct Foo{AC <: AbstractArray}
    float_array::AC{Float64}
    int_array::AC{Int}
end

```

Unfortunately, this throws an error:

```julia
ERROR: TypeError: in Type{...} expression, expected UnionAll, got a value of type TypeVar

```

Is that possible to be defined in the type or do I have to make both a subtype of AbstractArray and use inner constructors to force the same type?

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [July 22, 2025, 3:23pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945/2 "2025-07-22T15:23:00Z")

</div>

I think the only way is to declare two parameters:

```julia
struct Foo{ACF <: AbstractArray{Float64}, ACI <: AbstractArray{Int}}
    float_array::ACF
    int_array::ACI
end

```

---

<div class="post-metadata">

**Author:** ![zsoerenm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zsoerenm/32/664_2.png) [@zsoerenm](https://discourse.julialang.org/u/zsoerenm)\
**Post date:** [July 22, 2025, 3:26pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945/3 "2025-07-22T15:26:12Z")

</div>

This doesn’t meet my requirements, though. Your example would allow one to be a type of Array and the other could be a CuArray.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [July 22, 2025, 3:27pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945/4 "2025-07-22T15:27:07Z")

</div>

As stated above, you will need two distinct type parameters for this. If you want to ensure they have the same outer type, consider validating that in an [inner constructor](https://docs.julialang.org/en/v1/manual/constructors/#man-inner-constructor-methods).

---

<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:** [July 22, 2025, 3:30pm UTC](https://discourse.julialang.org/t/define-struct-with-two-fields-that-have-the-same-abstract-type-but-different-specialization/130945/5 "2025-07-22T15:30:59Z")

</div>

You can’t put parameters in just the type part of a parametric type, only the parameter part or the whole thing; for example, `Foo{Vector{Int}}` is a valid type, but the implied `Vector{Int}{Float64}` isn’t. Also note that the direct `supertype` of a concrete type `AC{Float64}` is actually `AbstractArray{Float64}`. `AC{T} where T` is an iterated union of types, which like `Union`s is a way to group types into an ad-hoc supertype; `AC{Int}` and `AC{Float64}` are about as related to each other via `AC` as `Int` and `Float64` are via `Union{Int, Float64}` or `Any`, which limits how we can define type parameters. Best I could do without constructor validation, and it’s not even close:

```julia
julia> struct Foo{AC<:AbstractArray, T<:AC, S<:AC}
           int_array::T
           float_array::S
       end

julia> Foo{Vector, Vector{Int}, Vector{Float64}}
Foo{Vector, Vector{Int64}, Vector{Float64}}

julia> Foo{AbstractVector{Int}, DenseVector{Int}, Vector{Int}} # horrible
Foo{AbstractVector{Int64}, DenseVector{Int64}, Vector{Int64}}

```
