# Destructuring Type Parameters

**URL:** <https://discourse.julialang.org/t/destructuring-type-parameters/81881>\
**Category:** General Usage\
**Tags:** parametric-types, parametric-methods\
**Created:** [May 29, 2022, 7:06pm UTC](https://discourse.julialang.org/t/destructuring-type-parameters/81881 "2022-05-29T19:06:57Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![HashBrown](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hashbrown/32/43601_2.png) [@HashBrown](https://discourse.julialang.org/u/HashBrown)\
**Post date:** [May 29, 2022, 7:06pm UTC](https://discourse.julialang.org/t/destructuring-type-parameters/81881/1 "2022-05-29T19:06:57Z")

</div>

Is there any way to destructure type parameters when defining parametric types and methods.

Something along the lines of

```julia
struct Foo{U{T}} end

# Examples
Foo{Vector{Int}}()

Foo{AbstractArray{Int}}()

```

I know this particular example is simple to resolve with

```julia
struct Foo{U, T} end

```

but I have a more complicated situation in mind where the constraints on the types create redundancies in the parameterizations in a way where if I could destructure a type parameter I could infer another one

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [May 29, 2022, 8:12pm UTC](https://discourse.julialang.org/t/destructuring-type-parameters/81881/2 "2022-05-29T20:12:52Z")

</div>

Could you clarify your goal/what problem are you trying to solve?

---

<div class="post-metadata">

**Author:** ![HashBrown](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hashbrown/32/43601_2.png) [@HashBrown](https://discourse.julialang.org/u/HashBrown)\
**Post date:** [May 29, 2022, 11:18pm UTC](https://discourse.julialang.org/t/destructuring-type-parameters/81881/3 "2022-05-29T23:18:25Z")

</div>

Say I want to create types for nodes that will exist in a DAG. Each node contains a `val` that will be updated on each iteration of an event loop. The type of `val` is the `OutputType` of the node.

One can use meta nodes which can provide insight into other nodes. For example you could have a node `A` with an `OutputType` of `Float64`. You could also have a meta node that stores the maxiumim of another node. The `Max` node’s `OutputType` would also be `Float64` and it would be parameterized by the type of `A` as well. (The type of every node in the DAG is unique as it fully dictates the behavior of the node)

For example this can be achieved by the code below:

```julia
abstract type Node{OutputType} end

struct Foo{OutputType} <: Node{OutputType}
    val :: OutputType
end

struct Max{OutputType, NodeType <: Node{OutputType}} <: Node{OutputType}
    val :: OutputType
end

# Example
Max{Float64, Foo{Float64}}(1e-20)

```

However the definition of `Max` is a little redundant. The `OutputType` is fully determined by the `NodeType` but yet the programmer has to specify it. See above how `Float64` is used twice in the construction of the example.

---

<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:** [May 29, 2022, 11:43pm UTC](https://discourse.julialang.org/t/destructuring-type-parameters/81881/4 "2022-05-29T23:43:57Z")

</div>

It’s just that when you write a type with the built-in curly-braces syntax, you have to be explicit. `Max{Float64, Foo{Int}}` is perfectly legal syntax, and it only errors because the `OutputType` doesn’t match in the specific `Max` definition. It makes no sense to allow `Max2{Float32, Foo2}` syntax as a shorthand for all definitions.

The other part of the issue is that because you didn’t use `NodeType` to annotate any fields, there wasn’t a default `Max` constructor method. It makes sense, `Max(val)` alone cannot tell you the entire `NodeType`. However, you can make a constructor method that accepts the needed type information. Here’s a quick one, though I bet it could be improved: `Max(val, T::UnionAll) = Max{typeof(val), T{typeof(val)} }(val)`. You then just write `Max(1e-20, Foo)`.
