# How to create struct where type parameter is a parametric type itself?

**URL:** <https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723>\
**Category:** New to Julia\
**Created:** [July 18, 2023, 11:31am UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723 "2023-07-18T11:31:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 18, 2023, 11:31am UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/1 "2023-07-18T11:31:47Z")

</div>

I’m simplifying my code here, but the problem is like this:

```julia
struct MyType{Array{T<:Real}}
    field::T
    function MyType(x::Array{T}) where T<:Real
        new{Array{T}}(sum(x))
    end
end

```

A workaround I found is to write struct MyType{T\<:Real, S\<:Array{T}} instead. Is this the only way to go about this? Why doesn’t the initial syntax work?

---

<div class="post-metadata">

**Author:** ![palday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palday/32/12640_2.png) [@palday](https://discourse.julialang.org/u/palday)\
**Post date:** [July 18, 2023, 11:53am UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/2 "2023-07-18T11:53:41Z")

</div>

In the real example, do you care about the `Array` or do you only care about its type parameter `T`? If you only care about `T`, you could do something like

```julia
struct MyType{T<:Real}
    field::T
    function MyType(x::Array{T}) where T<:Real
        new{T}(sum(x))
    end
end

```

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 18, 2023, 12:05pm UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/3 "2023-07-18T12:05:57Z")

</div>

I actually do care about the parametric type (which isn’t `Array` in the real example). It’s a series of other composite types I made and I’d like `MyType` to be able to take them as a parameter.

---

<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 18, 2023, 2:52pm UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/4 "2023-07-18T14:52:26Z")

</div>

The pattern to achieve this is usually to have additional “redundant” type parameters. An example of such a type is `SubArray`, which is produced by `view`:

```julia
julia> typeof(view(zeros(5,5),1:3,3))
SubArray{Float64, 1, Matrix{Float64}, Tuple{UnitRange{Int64}, Int64}, true}

```

The first parameter is the `eltype`, the second is the dimension of the `view`, the third is the parent array type (which includes the `eltype` as a sub-parameter, in this case), the fourth is the type of the axis slices, and the fifth flags whether the view is strided.

Note that the parent type and the slice types are sufficient to deduce the other three parameters. Nevertheless, they are added as parameters because they are useful for dispatching other functions.

So in your case, you might parameterize your struct like this

```julia
julia> struct MyType{T, A<:AbstractArray{T}}
           field::T
           function MyType(x::A) where {T<:Real, A<:AbstractArray{T}}
               new{T,A}(sum(x))
           end
       end

julia> MyType(rand(10))
MyType{Float64, Vector{Float64}}(5.716220410885628)

```

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 19, 2023, 7:11pm UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/5 "2023-07-19T19:11:11Z")

</div>

Thanks this makes sense. I always wondered why I kept seeing this redundant pattern in places. So the idea is there `where` doesn’t accept nested parametrized types, so you have to declare the inner parameter seperately and then it’s fine? Could your code be `struct MyType{T, Array{T}}` instead?

---

<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 19, 2023, 7:33pm UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/6 "2023-07-19T19:33:04Z")

</div>

> [@Jad\_Zeitouni](#):
>
> Could your code be `struct MyType{T, Array{T}}` instead?

Not as far as I’m aware. You can only have parameters declared there, plus any type bounds you want to impose on them. But you could write `struct MyType{T, A<:Array{T}}`.

Honestly, the type bounds there aren’t even really important and I seldom impose them. They only exist to throw errors when you try to construct invalid instances, but don’t usually improve performance or have other benefits. _Maybe_ there are small benefits with some recent changes to abstract inlining when there are _already_ existing type instabilities? But I haven’t experimented and it’s seldom relevant to well-written code.

Also, since you keep writing it, I’ll point out that `Array{T}` is not a concrete type so no instance of one can exist. You can still write (most) code with it, but it may produce type instabilities.

```julia
julia> (Array{T} where T) == (Array{T,D} where {T,D})
true

```

You probably mean to write `Array{T,1}` a.k.a. `Vector{T}`. Or perhaps you really do want the dimension parameter to be free, in which case you definitely need `A<:Array{T}`. But I don’t see why `1:5`, which `isa UnitRange{Int}`, shouldn’t be a valid input, which is why I suggested the more permissive `A<:AbstractArray{T}`.

---

<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 19, 2023, 8:05pm UTC](https://discourse.julialang.org/t/how-to-create-struct-where-type-parameter-is-a-parametric-type-itself/101723/7 "2023-07-19T20:05:44Z")

</div>

> [@Jad\_Zeitouni](#):
>
> Could your code be `struct MyType{T, Array{T}}` instead?

That part _is_ the where clause of the struct. `where {T, Array{T}}` is more obviously not valid; you need the `S<:Array{T}` so `S` could annotate something (though nothing in this case). Your working struct probably looks like this:

```julia
struct MyType{T<:Real, S<:Array{T}}
  field::T
  function MyType(x::Array{T}) where T<:Real
    new{T,typeof(x)}(sum(x))
  end
end

```

A weird alternative is to store the array type in a field instead, and you wouldn’t even need to pass a full array instance sometimes. The type field does take up extra space though. It’s also possible to parameterize this by the type, but it does make the array type field abstractly annotated.

```julia
struct MyType2{T<:Real}
  field::T
  arraytype::DataType
  function MyType2(x::Array{T}) where T<:Real
    new{T}(sum(x), typeof(x))
  end
end

```
