# StaticArrays, parametric types, type stability

**URL:** https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095
**Category:** General Usage
**Tags:** parametric-types, type-stability, staticarrays
**Created:** [April 12, 2021, 11:39am UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095 "2021-04-12T11:39:12Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [April 12, 2021, 11:39am UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/1 "2021-04-12T11:39:12Z")

</div>

Here is a little snippet of code

```julia
using StaticArrays

struct JustMyType{N,M}
    a::Vector{<:SMatrix{N,M,Float64}}
    b:: SMatrix{N,M,Float64}
end

j = JustMyType([SMatrix{2,3,Float64}(randn(2,3)) for i=1:4],
                SMatrix{2,3,Float64}(randn(2,3)) )

```

Note the `<:` . My previous version of the code without it fails, because `SMatrix{N,M,Float64}` is an abstract type (the single concrete type corresponding to it being `SMatrix{N,M,Float64,N*M}`.

1. Coding

```julia
    a::Vector{SMatrix{N,M,Float64,N*M}}

```

does not work - one cannot multiply type parameters.

1. For some reason I do not understand, but likely related to `N*M` not being legit, the developers of `StaticArrays.jl` had to have a length parameter to an `SMatrix`. One way I could write my code is to let `JustMyType` also have this parameter. However, I am not keen, because in a real world situation with many StaticArrays in my type, this generates many parameters, a source of bugs and poor readability of code and `typeof`outputs.

2. As coded now, my structure has fields of abstract types, and I am set for type-unstable code.

I’ll have to chose between readability and performance, _unless_ you can point out something I missed!

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [April 12, 2021, 12:04pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/2 "2021-04-12T12:04:52Z")

</div>

> [@Philippe\_Maincon1](#):
>
> I’ll have to chose between readability and performance, _unless_ you can point out something I missed!

Your requirements are not very clear, but something like

```julia
struct JustMyType{T}
    a::Vector{T}
    b::T
end

```

should work.

Don’t overtype things. If absolutely necessary, you can make `T <: AbstractMatrix`, or validate that it is an `SMatrix` in the constructor, or use a triangular parametrization like

```julia
struct JustMyType{N,M,T<:SMatrix{N,M}}
    a::Vector{T}
    b::T
end

```

you need `N` and `M` as a type parameter directly.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [April 12, 2021, 12:21pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/3 "2021-04-12T12:21:10Z")

</div>

> [@Tamas\_Papp](#):
>
> Your requirements are not very clear, but something like

I forgot to mention, as you propose

```julia
struct JustMyType{T}
    a::Vector{T}
    b::T
end

```

which I had in a previous version of my code. It’s neat and performant code. However, the real-world equivalent (a structure with many different arrays) of typing `typeof(j)`returns a type description with the detailed description of the type of all these arrays. I want the user of my code to have a “friendly” relation to `typeof(j)`.

So to be more specific. I wish to refactor the above code to have

- few type parameters - not having to provide `L` which is obviously `M` times `N`
- integer type parameters (for readability of the concrete type of `j`), so `T` is not welcome.
- type stability (no abstract fields).

Is that at all possible?

😀

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [April 12, 2021, 1:26pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/4 "2021-04-12T13:26:50Z")

</div>

> [@Philippe\_Maincon1](#):
>
> I want the user of my code to have a “friendly” relation to `typeof(j)` .

Sorry, I do not understand what you mean here.

> [@Philippe\_Maincon1](#):
>
> few type parameters - not having to provide `L` which is obviously `M` times `N`

The type system is not the place to express these kind of constraints. Extra type parameters of this kind are standard in Julia, and generally innocuous. You can, of course, design your user-facing API so that `L` does not need to be specified by the user — see how StaticArrays does it.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [April 12, 2021, 1:51pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/5 "2021-04-12T13:51:58Z")

</div>

> [@Tamas\_Papp](#):
>
> Sorry, I do not understand what you mean here.

The static arrays have elements have themselves complicated elements, so using your `T` patterm in a previous version of my real world code, `typeof` would return between 5 and 10 lines of hard-to-read details, and I was not happy with that.

As I said, I was fishing for ideas, but I believe now I was aware of all the options. I have now gone for a solution in which I accept the small annoyance of having `L` (and its real-world siblings) as an extra parameter to my type.

Tamas, it’s not the first time you help me: thank you again! 😀

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [April 12, 2021, 1:57pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/6 "2021-04-12T13:57:15Z")

</div>

> [@Philippe\_Maincon1](#):
>
> `typeof` would return between 5 and 10 lines of hard-to-read details, and I was not happy with that.

Yes, that’s a known issue, and people are working on it, see eg

> <https://github.com/JuliaLang/julia/issues/36517>
>
> Is there a way to omit type parameters? I think a lot of issues like https://git…hub.com/JuliaLang/julia/issues/36026 are hitting great points, but they are missing the key issue with stack traces because they are focused too much on minimal examples. Let's take a look at a very common example seen in the wild. Here a user uses a package function that autodiffs an un-autodiffable ODE definition:
> 
> \`\`\`julia
> using OrdinaryDiffEq
> cache = Ref(0.0)
> function lorenz(du,u,p,t)
> cache\[\] = u\[2\] - u\[1\]
> du\[1\] = 10.0(cache\[\])
> du\[2\] = u\[1\]\*(28.0-u\[3\]) - u\[2\]
> du\[3\] = u\[1\]\*u\[2\] - (8/3)\*u\[3\]
> end
> u0 = \[1.0;0.0;0.0\]
> tspan = (0.0,100.0)
> prob = ODEProblem(lorenz,u0,tspan)
> sol = solve(prob,Rosenbrock23())
> \`\`\`
> 
> And the error? Let me post it so we can fully understand its glory:
> 
> \`\`\`julia
> julia\> sol = solve(prob,Rosenbrock23())
> ERROR: TypeError: in setfield!, expected Float64, got ForwardDiff.Dual{Nothing,Float64,3}
> Stacktrace:
> \[1\] setproperty! at .\\Base.jl:34 \[inlined\]
> \[2\] setindex!(::Base.RefValue{Float64}, ::ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3}) at .\\refvalue.jl:33
> \[3\] lorenz(::Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1}, ::Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1}, ::DiffEqBase.NullParameters, ::Float64) at D:\\OneDrive\\Computer\\Desktop\\test.jl:49
> \[4\] ODEFunction at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\diffeqfunction.jl:248 \[inlined\]
> \[5\] UJacobianWrapper at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\function\_wrappers.jl:15 \[inlined\]
> \[6\] forwarddiff\_color\_jacobian!(::Array{Float64,2}, ::DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters}, ::Array{Float64,1}, ::SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing}) at C:\\Users\\accou\\.julia\\packages\\SparseDiffTools\\MR3Wm\\src\\differentiation\\compute\_jacobian\_ad.jl:175
> \[7\] jacobian! at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\derivative\_wrappers.jl:99 \[inlined\]
> \[8\] calc\_J! at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\derivative\_utils.jl:112 \[inlined\]
> \[9\] calc\_W!(::Array{Float64,2}, ::OrdinaryDiffEq.ODEIntegrator{Rosenbrock23{0,true,DefaultLinSolve,DataType},true,Array{Float64,1},Nothing,Float64,DiffEqBase.NullParameters,Float64,Float64,Float64,Array{Array{Float64,1},1},ODESolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},Rosenbrock23{0,true,DefaultLinSolve,DataType},OrdinaryDiffEq.InterpolationData{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}}},DiffEqBase.DEStats},ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}},OrdinaryDiffEq.DEOptions{Float64,Float64,Float64,Float64,typeof(DiffEqBase.ODE\_DEFAULT\_NORM),typeof(opnorm),CallbackSet{Tuple{},Tuple{}},typeof(DiffEqBase.ODE\_DEFAULT\_ISOUTOFDOMAIN),typeof(DiffEqBase.ODE\_DEFAULT\_PROG\_MESSAGE),typeof(DiffEqBase.ODE\_DEFAULT\_UNSTABLE\_CHECK),DataStructures.BinaryHeap{Float64,DataStructures.LessThan},DataStructures.BinaryHeap{Float64,DataStructures.LessThan},Nothing,Nothing,Int64,Tuple{},Tuple{},Tuple{}},Array{Float64,1},Float64,Nothing,OrdinaryDiffEq.DefaultInit}, ::Nothing, ::OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}}, ::Float64, ::Bool, ::Bool) at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\derivative\_utils.jl:453
> \[10\] calc\_rosenbrock\_differentiation! at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\derivative\_utils.jl:511 \[inlined\]
> \[11\] perform\_step!(::OrdinaryDiffEq.ODEIntegrator{Rosenbrock23{0,true,DefaultLinSolve,DataType},true,Array{Float64,1},Nothing,Float64,DiffEqBase.NullParameters,Float64,Float64,Float64,Array{Array{Float64,1},1},ODESolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},Rosenbrock23{0,true,DefaultLinSolve,DataType},OrdinaryDiffEq.InterpolationData{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}}},DiffEqBase.DEStats},ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}},OrdinaryDiffEq.DEOptions{Float64,Float64,Float64,Float64,typeof(DiffEqBase.ODE\_DEFAULT\_NORM),typeof(opnorm),CallbackSet{Tuple{},Tuple{}},typeof(DiffEqBase.ODE\_DEFAULT\_ISOUTOFDOMAIN),typeof(DiffEqBase.ODE\_DEFAULT\_PROG\_MESSAGE),typeof(DiffEqBase.ODE\_DEFAULT\_UNSTABLE\_CHECK),DataStructures.BinaryHeap{Float64,DataStructures.LessThan},DataStructures.BinaryHeap{Float64,DataStructures.LessThan},Nothing,Nothing,Int64,Tuple{},Tuple{},Tuple{}},Array{Float64,1},Float64,Nothing,OrdinaryDiffEq.DefaultInit}, ::OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}}, ::Bool) at 
> C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\perform\_step\\rosenbrock\_perform\_step.jl:40
> \[12\] perform\_step! at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\perform\_step\\rosenbrock\_perform\_step.jl:27 \[inlined\]
> \[13\] solve!(::OrdinaryDiffEq.ODEIntegrator{Rosenbrock23{0,true,DefaultLinSolve,DataType},true,Array{Float64,1},Nothing,Float64,DiffEqBase.NullParameters,Float64,Float64,Float64,Array{Array{Float64,1},1},ODESolution{Float64,2,Array{Array{Float64,1},1},Nothing,Nothing,Array{Float64,1},Array{Array{Array{Float64,1},1},1},ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem},Rosenbrock23{0,true,DefaultLinSolve,DataType},OrdinaryDiffEq.InterpolationData{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Array{Float64,1},1},Array{Float64,1},Array{Array{Array{Float64,1},1},1},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}}},DiffEqBase.DEStats},ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},OrdinaryDiffEq.Rosenbrock23Cache{Array{Float64,1},Array{Float64,1},Array{Float64,1},Array{Float64,2},Array{Float64,2},OrdinaryDiffEq.Rosenbrock23Tableau{Float64},DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},DefaultLinSolve,SparseDiffTools.ForwardColorJacCache{Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3},1},Array{Float64,1},Array{Array{Tuple{Bool,Bool,Bool},1},1},UnitRange{Int64},Nothing},Array{ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.TimeGradientWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Array{Float64,1},DiffEqBase.NullParameters},Float64},Float64,1},1}},OrdinaryDiffEq.DEOptions{Float64,Float64,Float64,Float64,typeof(DiffEqBase.ODE\_DEFAULT\_NORM),typeof(opnorm),CallbackSet{Tuple{},Tuple{}},typeof(DiffEqBase.ODE\_DEFAULT\_ISOUTOFDOMAIN),typeof(DiffEqBase.ODE\_DEFAULT\_PROG\_MESSAGE),typeof(DiffEqBase.ODE\_DEFAULT\_UNSTABLE\_CHECK),DataStructures.BinaryHeap{Float64,DataStructures.LessThan},DataStructures.BinaryHeap{Float64,DataStructures.LessThan},Nothing,Nothing,Int64,Tuple{},Tuple{},Tuple{}},Array{Float64,1},Float64,Nothing,OrdinaryDiffEq.DefaultInit}) at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\solve.jl:425
> \[14\] \_\_solve(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::Rosenbrock23{0,true,DefaultLinSolve,DataType}; kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\solve.jl:5
> \[15\] \_\_solve at C:\\Users\\accou\\.julia\\dev\\OrdinaryDiffEq\\src\\solve.jl:4 \[inlined\]
> \[16\] solve\_call(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::Rosenbrock23{0,true,DefaultLinSolve,DataType}; merge\_callbacks::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:96
> \[17\] solve\_call at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:69 \[inlined\]
> \[18\] #solve\_up#454 at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:122 \[inlined\]
> \[19\] solve\_up at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:110 \[inlined\]
> \[20\] #solve#453 at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:106 \[inlined\]
> \[21\] solve(::ODEProblem{Array{Float64,1},Tuple{Float64,Float64},true,DiffEqBase.NullParameters,ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}},DiffEqBase.StandardODEProblem}, ::Rosenbrock23{0,true,DefaultLinSolve,DataType}) at C:\\Users\\accou\\.julia\\dev\\DiffEqBase\\src\\solve.jl:104
> \[22\] top-level scope at none:0
> \`\`\`
> 
> It's absolutely fantastic that Julia gives you all of the information in the world, letting you know everything about the problem all of the way down because it's all implemented in Julia. But... it's daunting. For most people, this is only harmful because there's too much information clouding what's really the issue. 
> 
> \## The Core Issue
> 
> I tried to put a Dual number into a container for Floats. But Julia doesn't tell me this, it tells me I tried to put a \`ForwardDiff.Dual{ForwardDiff.Tag{DiffEqBase.UJacobianWrapper{ODEFunction{true,typeof(lorenz),UniformScaling{Bool},Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing,Nothing},Float64,DiffEqBase.NullParameters},Float64},Float64,3}\` into a container for floats. Is all of that necessary to the average user? I think there should probably be a way to limit this information, i.e. \`ForwardDiff.Dual{...}\`.
> 
> However, it's not as simple as just doing that to all type parameters since here we wanted to know that it's:
> 
> \`\`\`julia
> \[2\] setindex!(::Base.RefValue{Float64}, ::ForwardDiff.Dual{...,Float64}) at .\\refvalue.jl:33
> \`\`\`
> 
> so we need to print the \`Float64\` but omit the other part. 
> 
> \## Remedy
> 
> My proposed remedy is a system like \`show\_simplified\_type\` where a package can choose the simplified printing form of its type. So \`ForwardDiff.Dual\` can define \`ForwardDiff.Dual{...,Float64}\` as its simplified print out, and by default this is all that's shown. Then in the expanded stacktrace forms of https://github.com/JuliaLang/julia/issues/36026 it could be set to give the entire information, but I think this will be a lot more helpful for the vast majority of people.

Happy to help!

---

<div class="post-metadata">

### Author: ![jacobadenbaum](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@jacobadenbaum](https://discourse.julialang.org/u/jacobadenbaum)
#### Post date: [April 12, 2021, 3:59pm UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/7 "2021-04-12T15:59:43Z")

</div>

Also consider using the macros defined by ConcreteStructs.jl! They can simplify some of these extraneous type parameters, and will give you more terse and readable type printouts for free. I find it makes working with these parametric structs a bit more user friendly.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon1](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Philippe\_Maincon1](https://discourse.julialang.org/u/Philippe_Maincon1)
#### Post date: [April 13, 2021, 4:51am UTC](https://discourse.julialang.org/t/staticarrays-parametric-types-type-stability/59095/8 "2021-04-13T04:51:10Z")

</div>

> [@jacobadenbaum](#):
>
> ConcreteStructs.jl

but… this is gold! 😀 I’ll have to play with it to understand the full potential
