# Extracting type parameters from type with many parameters

**URL:** <https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843>\
**Category:** General Usage\
**Tags:** type, parametric-types, parametric-methods\
**Created:** [May 28, 2022, 7:45pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843 "2022-05-28T19:45:35Z")\
**Posts on this page:** 7\
**Page:** 1

<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 28, 2022, 7:45pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/1 "2022-05-28T19:45:35Z")

</div>

I’ve got a type with six type parameters, something like this:

```julia
struct MyType{A <: S, a0, a1, B <: T, b0, b1} end

```

My problem is that I want access to the type parameters in functions which take MyType values as arguments.  
The best way of doing this that comes to mind is this:

```julia
my_a_type(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = A
my_a0(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = Val(a0)
my_a1(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = Val(a1)
my_b_type(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = B
my_b0(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = Val(b0)
my_b1(::MyType{A, a0, a1, B, b0, b1}) where {A <: S, a0, a1, B <: T, b0, b1} = Val(b1)

```

But this is repetitive, especially as the parameter names would be longer in real code. Is there a better way, perhaps?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [May 28, 2022, 8:02pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/2 "2022-05-28T20:02:11Z")

</div>

if you need to do this it feels like they should be field instead of type parameter?

---

<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 28, 2022, 8:15pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/3 "2022-05-28T20:15:13Z")

</div>

Given a concrete type `Y`, a way you can get its parameter values is `Y.parameters`. Wouldn’t work on `MyType` itself because it’s an abstract type where the parameters aren’t specified, but it’d work on `MyType{Int, 1, :one, Float64, 3.5, 2}`. `.parameters` is not part of the public interface, so don’t count on it still being there in future versions of Julia.

The full struct has fields, right? It’s more typical to compute with those fields or use `typeof` if you really need a field’s type. It’s very rare to get parameters directly from a type, and when it happens, a specific parameter is accessed by an isolated method like `ndims` (very similar to `my_b_type`) rather than some generic `.parameters`-based method. The idea is that if you’re treating something like _data_ to compute on, it should usually be structured as instances/fields instead of type-annotations/parameters.

---

<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 28, 2022, 8:28pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/4 "2022-05-28T20:28:59Z")

</div>

Oh, I get it. `A` and `B` I can get via `typeof` on some already-existing struct fields; and for `a0`, `a1`, `b0`, `b1` I just add some fields of type Val.

---

<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 28, 2022, 11:31pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/5 "2022-05-28T23:31:48Z")

</div>

It’s not possible to say more on how you should organize the data without more context, but I would caution against that sort of information redundancy between fields and type parameters for `a0, a1, b0, b1`. It would mean storing the same type information in _each_ and every instance, which can add up.

Is it at all possible that `a0, a1, b0, b1` could be refactored entirely as fields instead of parameters for the type? Generally information is put in parameters because it should be known at compile-time, such as for dispatching to different methods or compiling more performant code. The downside is that there are more types to compile each method for. 6 parameters is a _LOT_; assuming there are only 2 values for each parameter, that’s 2^6 = 64 types right off the bat. If your ratio of concrete types to instances over repeated runs in practice approaches 1:1 instead of 0:1, your runtime improvements could easily be swamped by compile-time latency and compiled code bloat. I know that it’s not always obvious how much information should be put in types, but an example of a 1:1 ratio is `struct CompileTimeInt{N} end`.

---

<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 28, 2022, 11:37pm UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/6 "2022-05-28T23:37:26Z")

</div>

> [@Benny](#):
>
> caution against that sort of information redundancy between fields and type parameters for `a0, a1, b0, b1` . It would mean storing type information in _each_ instance, which can add up.

When you say “add up” you seem to be implying that adding Val fields would make my structs heavier, however I think this can’t be true, because each Val type is a singleton type, so instances shouldn’t consume space.

Example:

```julia
julia> sizeof((Val(7), Val(3)))
0

```

---

<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, 12:07am UTC](https://discourse.julialang.org/t/extracting-type-parameters-from-type-with-many-parameters/81843/7 "2022-05-29T00:07:05Z")

</div>

Oh that’s interesting, I never noticed that information in type parameters could trim a field’s memory usage to 0. I suppose the memory usage of instances with `Val` fields would scale with the number of unique `Val` types, not number of instances.

In the case of `(Val(7), Val(3))`, the `Tuple` type completely contains the information, so the instance doesn’t have to hold anything. But when a type, like an `Array`, can’t contain all the information, there is a memory cost; I don’t know the implementation detail exactly, but a `Val` array’s element looks pointer-sized.

> **Sizes of tuple or array before and after 1 additional Int8 element**
>
> ```julia
> julia> Base.summarysize( Int8.( (7,3) ) )
> 2
> julia> Base.summarysize( Int8.( (7,3,1) ) )
> 3
> julia> Base.summarysize( Val.(Int8.( (7,3) ) ) )
> 0
> julia> Base.summarysize( Val.(Int8.( (7,3,1) ) ) )
> 0
> julia> Base.summarysize( Int8.( [7,3] ) )
> 42
> julia> Base.summarysize( Int8.( [7,3,1] ) )
> 43
> julia> Base.summarysize( Val.(Int8.( [7,3] ) ) )
> 56
> julia> Base.summarysize( Val.(Int8.( [7,3,1] ) ) )
> 64
> 
> ```
