# Dynamic union of parametric types

**URL:** https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247
**Category:** General Usage
**Tags:** parametric-types, types
**Created:** [May 22, 2025, 12:19pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247 "2025-05-22T12:19:34Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 12:19pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/1 "2025-05-22T12:19:34Z")

</div>

I am trying to define Union types that collect different instances of different types, it should be possible to append newer types that are defined later on, so that the union types can grow

here an example:

```julia
module Elements

CElems{C,M} = Union{} where {C,M}
Elems2D{C,M} = Union{} where {C,M}
Elems3D{C,M} = Union{} where {C,M}

struct quad{C,M} end
struct tria{C,M} end
struct hexa{C,M} end
struct tetra{C,M} end

Elems2D{C,M} = Union{CElems{C,M}, quad{C,M}} where {C,M}
Elems2D{C,M} = Union{CElems{C,M}, tria{C,M}} where {C,M}

Elems3D{C,M} = Union{CElems{C,M}, hexa{C,M}, tetra{C,M}} where {C,M}

CElems{C,M} = Union{Elems2D{C,M}, Elems3D{C,M}} where {C,M}

end

```

it gives me this error, on line 15 (`Elems2D{C,M} = Union{CElems{C,M}, quad{C,M}} where {C,M}`)

```julia
ERROR: LoadError: TypeError: in Type{...} expression, expected UnionAll, got Type{Union{}}

```

things work if the types are not parametric, but I do need that

hope I have been clear about what I am trying to obtain

---

<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 22, 2025, 12:37pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/2 "2025-05-22T12:37:38Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> Union types that collect different instances of different types, it should be possible to append newer types that are defined later on, so that the union types can grow

Sounds like what you actually want is `abstract type`?

> [@Andrea\_Vigliotti](#):
>
> ```julia
> CElems{C,M} = Union{} where {C,M}
> Elems2D{C,M} = Union{} where {C,M}
> Elems3D{C,M} = Union{} where {C,M}
> 
> ```

This is nonsensical: `Union{} where {C,M}` is just the bottom type (`Union{}`), because the body of the `UnionAll`, `Union{}`, does not depend on either of the type parameters, `C` and `M`. See it in the REPL:

```julia-repl
julia> Union{} where {C,M}
Union{}
 
julia> CElems{C,M} = Union{} where {C,M}
Union{}

```

---

<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 22, 2025, 12:45pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/3 "2025-05-22T12:45:22Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> hope I have been clear about what I am trying to obtain

Personally, I don’t get it. In fact, this very much seems like an _XY problem_:

- [https://xyproblem.info](https://xyproblem.info)

- [XY problem - Wikipedia](https://en.wikipedia.org/wiki/XY_problem)

So, could you tell more about the what you’re trying to solve, instead of the attempted solution?

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 12:46pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/4 "2025-05-22T12:46:35Z")

</div>

I thought about `abstract type` but I don’t know if it is possible to make `quad` both a subtype of `CElems` and `Elems2D`.

it appears to me that you can define a type as a subtype of an `abstract type` only at creation and `concrete types` can only have one parent `abstract type` or am I wrong?

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 12:49pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/5 "2025-05-22T12:49:51Z")

</div>

I need to define types for different kind of elements in a Finite Element software, so that later on I can define functions that work on 2D elements, or 3D elements, or continuous elements (that can be either 2D or 3D), and so on with a rich landscapes of elements with different features that have different tags attached (hope it is not too much convoluted)

---

<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 22, 2025, 12:59pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/6 "2025-05-22T12:59:04Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> I thought about `abstract type` but I don’t know if it is possible to make `quad` both a subtype of `CElems` and `Elems2D`.

There is no multiple inheritance in Julia. So, no, a concrete type can’t subtype two different abstract types, except if one of the two abstract types already subtypes the other one.

> [@Andrea\_Vigliotti](#):
>
> define a type as a subtype of an `abstract type` only at creation and `concrete types` can only have one parent `abstract type` or am I wrong?

You’re right on both counts.

> [@Andrea\_Vigliotti](#):
>
> types for different kind of elements in a Finite Element software, so that later on I can define functions that work on 2D elements, or 3D elements, or continuous elements (that can be either 2D or 3D), and so on with a rich landscapes of elements with different features that have different tags attached

Perhaps a good approach would be to give your types what is sometimes called “traits”, and then dispatch on the traits instead of on your types directly. Perhaps something like this:

```julia
struct Elems2D end
struct Elems3D end
struct CElems end

"""
    trait(x)

Return `Elems2D()` for two-dimensional elements, `Elems3D()` for three-dimensional elements or `CElems()` for continuous elements.
"""
function trait end

```

An example of where this pattern is used is `Base.IteratorSize`.

---

<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 22, 2025, 1:08pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/7 "2025-05-22T13:08:23Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> ```julia
> Elems2D{C,M} = Union{CElems{C,M}, quad{C,M}} where {C,M}
> Elems2D{C,M} = Union{CElems{C,M}, tria{C,M}} where {C,M}
> 
> Elems3D{C,M} = Union{CElems{C,M}, hexa{C,M}, tetra{C,M}} where {C,M}
> 
> CElems{C,M} = Union{Elems2D{C,M}, Elems3D{C,M}} where {C,M}
> 
> ```

Looking at your original code again, it’s quite possible what you want could be achieved just using `Union` (and possibly `UnionAll`), however it’s still not clear to me what is the expected result. Could you sketch the desired subtyping relationship between the types you want defined?

For example:

- from `CElems{C,M} = Union{Elems2D{C,M}, Elems3D{C,M}}` it seems like you want `(Elems2D <: CElems) && (Elems3D <: CElems)`

- from `Elems3D{C,M} = Union{CElems{C,M}, hexa{C,M}, tetra{C,M}}` it seems like you want `CElems <: Elems3D`

The implication is `Elems3D == CElems`, and, similarly, `Elems2D == CElems`, which is surely not what you actually want.

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 1:18pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/8 "2025-05-22T13:18:26Z")

</div>

> [@nsajko](#):
>
> The implication is `Elems3D == CElems`, and, similarly, `Elems2D == CElems`, which is surely not what you actually want.

correct there are other elements that are `Elems3D` but are not `CElems`, and so on

The Union works if I define all of the atomic types first and then define the unions, but I really want it to be dynamic

at the same time union can be dynamic (i.e. I can append new atomic types to existing unions) but on if the unions do not have parameters, which I need to correctly dispatch over the proper function

---

<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 22, 2025, 1:19pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/9 "2025-05-22T13:19:33Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> union can be dynamic (i.e. I can append new atomic types to existing unions)

That’s not possible. Can you show what you mean?

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 1:25pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/10 "2025-05-22T13:25:37Z")

</div>

this does not give errors

```julia
module Elements

CElems = Union{}  
Elems2D = Union{}  
Elems3D = Union{}  

struct quad end
struct tria end
struct hexa end
struct tetra end

Elems2D = Union{CElems, quad}  
Elems2D = Union{CElems, tria}  

Elems3D = Union{CElems, hexa, tetra}  

CElems = Union{Elems2D, Elems3D}  

end

```

and at the REPL after running it i get :

```julia
julia> Elements.CElems
Union{Main.Elements.hexa, Main.Elements.tetra, Main.Elements.tria}

```

that why I think it should be possible to implement it with parameters also

---

<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 22, 2025, 1:29pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/11 "2025-05-22T13:29:46Z")

</div>

Your code example doesn’t “append new types to an existing union”. When you do this:

> [@Andrea\_Vigliotti](#):
>
> ```julia
> CElems = Union{}  
> Elems2D = Union{}  
> Elems3D = Union{}  
> 
> ```

You’re defining three global variables. Next, when you do this:

> [@Andrea\_Vigliotti](#):
>
> ```julia
> CElems = Union{Elems2D, Elems3D}
> 
> ```

… you’re not appending types to a preexisting `Union` (that’s not possible), you’re just reassigning to the global variable `CElems`, changing its value.

Does this help?

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 1:40pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/12 "2025-05-22T13:40:36Z")

</div>

but these line seem to append types to existing union

```julia
Elems2D = Union{CElems, quad}  
Elems2D = Union{CElems, tria}  

```

the first time `Elems2D` only contains `quad`, the second time it contains `quad` and `tria`

you are right `Elems2D` in the end is only a variable, but that does get me what I want

I must be seeing thing from some wrong angle

---

<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 22, 2025, 1:43pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/13 "2025-05-22T13:43:24Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> these line seem to append types to existing union

To “append to existing union” would mean to mutate an existing value. Instead what these lines do is reassign different values to existing variables.

---

<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 22, 2025, 1:44pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/14 "2025-05-22T13:44:43Z")

</div>

> [@nsajko](#):
>
> Could you sketch the desired subtyping relationship between the types you want defined?

In case it’s not clear, here I’m just asking you which of your types do you want to subtype which of your other types.

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 1:52pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/15 "2025-05-22T13:52:13Z")

</div>

it should be dynamic, as soon as new types are defined I wand to be able to append it to all the groups it belongs,

for instance a new element can be:

- “discrete” or “continuous”;
- “1D”, “2D”, or “3D”
- etc

more than subtypes I am try to tag types

---

<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 22, 2025, 1:54pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/16 "2025-05-22T13:54:56Z")

</div>

In that case I suggest you go with the “trait”-based approach I pointed to above. In your case discrete vs continuous would be one function, dimensionality would be another, etc. Then you add a method for this function when defining a new type.

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 1:59pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/17 "2025-05-22T13:59:08Z")

</div>

but I want to take advantage of the runtime multiple dispatch, so that I keep adding functions with the same name, and when I add new elements or functionality the same code will work with the old and the new elements

as far as I have understood the traits approach involves going trough a `case`/`switch` type of loop at run time which will slow things down enormously

---

<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 22, 2025, 2:00pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/18 "2025-05-22T14:00:53Z")

</div>

No. The naive way to implement it is a zero-cost abstraction (in C++ parlance), meaning all the computation happens at compilation time.

---

<div class="post-metadata">

### Author: ![Andrea\_Vigliotti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/andrea_vigliotti/32/7635_2.png) [@Andrea\_Vigliotti](https://discourse.julialang.org/u/Andrea_Vigliotti)
#### Post date: [May 22, 2025, 2:03pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/19 "2025-05-22T14:03:18Z")

</div>

I will look into it, but If I can get `Union` running as I intend I don’t have to write not a single new line of code

---

<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 22, 2025, 2:11pm UTC](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247/20 "2025-05-22T14:11:39Z")

</div>

> [@Andrea\_Vigliotti](#):
>
> ```none
> ERROR: LoadError: TypeError: in Type{...} expression, expected UnionAll, got Type{Union{}}
> 
> ```

Just to make clear the reason why this exception gets thrown:

- This happens on line `Elems2D{C,M} = Union{CElems{C,M}, quad{C,M}} where {C,M}`, specifically in the type application `CElems{C,M}`, where you try to apply `C` and `M` as type parameters to `CElems`.

- As shown in my first message, above, `CElems` is just `Union{}`.

- Thus `CElems{C,M}` is just `(Union{}){C,M}`, which obviously has to throw because `Union{}` doesn’t take any type parameters.

[Next page](https://discourse.julialang.org/t/dynamic-union-of-parametric-types/129247.md?page=2)
