# Get type containing the types of a set?

**URL:** <https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304>\
**Category:** New to Julia\
**Created:** [September 9, 2020, 3:12am UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304 "2020-09-09T03:12:23Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![pjentsch0](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pjentsch0/32/15148_2.png) [@pjentsch0](https://discourse.julialang.org/u/pjentsch0)\
**Post date:** [September 9, 2020, 3:12am UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/1 "2020-09-09T03:12:23Z")

</div>

Given a set of variables `[a,b,c...]`, I want to find the type `T` such that `typeof(a)<:T, typeof(b)<:T, ...`.

The reason I want to do this is that I have cache variables in my ODE system, which need to be able to adapt if one of the parameters or initial conditions is of type `Particles` or `Dual`. I know there is a `dualcache` thing in DiffEqBase.jl, but I would like a similar type of thing for arbitrary types.

Thanks!

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 9, 2020, 5:22am UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/2 "2020-09-09T05:22:55Z")

</div>

Your question and use case seem a bit different. Your question is asking for the most specific type `T` such that all elements of `x=[a,b,c,...]` are subtypes. Here’s a solution

```julia
typetree(T::DataType) = typetree!([T],supertype(T))
function typetree!(list, T::DataType)
    push!(list,supertype(T))
    return typetree!(list,supertype(T))
end
typetree!(list,T::Type{Any}) = return list

x = Any[2.0,1,UInt8(0)]
types = typetree.(typeof.(x))
umbrella_type = first(intersect(types...))

```

This recursively builds type trees for each type in `x` and then finds the set intersection. Since `intersect` preserves ordering, the first element of the intersection is the “umbrella” type for the collection.

I’m sure there’s a more elegant solution. However, it seems like your application just needs to know if any one of the elements of `x = [a,b,c...]` are of a specific type, which you can do with `any(typeof.(x).==Particle)` or `any(typeof.(x).==Dual)`.

---

<div class="post-metadata">

**Author:** ![pjentsch0](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pjentsch0/32/15148_2.png) [@pjentsch0](https://discourse.julialang.org/u/pjentsch0)\
**Post date:** [September 9, 2020, 1:53pm UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/3 "2020-09-09T13:53:18Z")

</div>

> Your question and use case seem a bit different. Your question is asking for the most specific type `T` such that all elements of `x=[a,b,c,...]` are subtypes. Here’s a solution…

Thanks!

> However, it seems like your application just needs to know if any one of the elements of `x = [a,b,c...]` are of a specific type, which you can do with `any(typeof.(x).==Particle)` or `any(typeof.(x).==Dual)`

Well, no I don’t think this works exactly. My use case was for my ODE function to work with _any_ `T <: Real` as a parameter, so I need my cache to be some concrete type `T2` such that `T<:T2`. I agree that it seems like overkill to use your solution for a problem where at most, I probably just have to add one or two lines if I want a new parameter type. I guess I was hoping there was a quick solution I was missing.

---

<div class="post-metadata">

**Author:** ![jlchan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlchan/32/10958_2.png) [@jlchan](https://discourse.julialang.org/u/jlchan)\
**Post date:** [September 9, 2020, 2:48pm UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/5 "2020-09-09T14:48:32Z")

</div>

> My use case was for my ODE function to work with _any_`T <: Real` as a parameter, so I need my cache to be some concrete type `T2` such that `T<:T2`

Ah, gotcha. I didn’t realize how the cache factored in.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 9, 2020, 3:06pm UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/6 "2020-09-09T15:06:46Z")

</div>

Check out “typejoin” as well (or maybe it’s called jointype… try both)

---

<div class="post-metadata">

**Author:** ![phg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phg/32/17184_2.png) [@phg](https://discourse.julialang.org/u/phg)\
**Post date:** [September 9, 2020, 3:49pm UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/7 "2020-09-09T15:49:12Z")

</div>

Does [this](https://stackoverflow.com/a/61854410/1346276) answer the question?

---

<div class="post-metadata">

**Author:** ![pjentsch0](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pjentsch0/32/15148_2.png) [@pjentsch0](https://discourse.julialang.org/u/pjentsch0)\
**Post date:** [September 9, 2020, 8:14pm UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/8 "2020-09-09T20:14:15Z")

</div>

Unfortunately not all concrete types `<:Real` are `isbits` so I can’t reinterpret… and usually `typejoin` doesn’t give concrete types.

I think `promote_type` is what I was looking for, thanks @phg!  
Here is my exploration if anyone is curious, or knows if I made an error somewhere. This minimal example uses the initial conditions, but I think the problem is similar with a cache variable.

```julia
using OrdinaryDiffEq
using Revise
using ForwardDiff

function f(du,u,p,t)
    du .= -p[2]*p[1]*u
end

u_0 = [10.0]
params = (1.0,2.0)
prob = ODEProblem(f,u_0,(0.0,10.0),params)
solve(prob,Tsit5()) #make sure it works with no fancy stuff

using MonteCarloMeasurements
params = (1.0,Particles(10,Normal(1.0,2.0)))
prob = ODEProblem(f,u_0,(0.0,10.0),params)
#solve(prob,Tsit5()) #this does not work

u_0 = typeof(params[2])[10.0]
prob = ODEProblem(f,u_0,(0.0,10.0),params)
# solve(prob,Tsit5()) #this does work!

#how to do this for (most) general types T<:Real?

element_types = typeof.(params)
u_0_2 = promote_type(element_types...)[10.0]
prob2 = ODEProblem(f,u_0_2,(0.0,10.0),params)
solve(prob2,Tsit5()) #this works, but maybe it's slower?

using BenchmarkTools
@btime solve(prob,Tsit5())
@btime solve(prob2,Tsit5())

#seems to work?
# 252.864 μs (6876 allocations: 841.17 KiB)
# 253.666 μs (6876 allocations: 841.17 KiB)

```

I wanted this to cover not just like, Particles, but also ForwardDiff with respect to particles, so `Dual{Particles}` and whatnot.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [September 11, 2020, 6:16am UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/9 "2020-09-11T06:16:31Z")

</div>

> [@pjentsch0](#):
>
> ```julia
> element_types = typeof.(params)
> u_0_2 = promote_type(element_types...)[10.0]
> prob2 = ODEProblem(f,u_0_2,(0.0,10.0),params)
> solve(prob2,Tsit5()) #this works, but maybe it's slower?
> 
> ```

I don’t think promoting the initial state to `Particles` will make it slower, since if your parameters are `Particles`, the state will become `Particles` eventually. By promoting the state manually, the ODE solver knows what types to use for internal variables.

On an unrelated note, maybe this is an MWE, but if not, you’ll probably see much better performance with `StaticParticles` if your really only want 10 particles. If you really want a lot of particles, stick with the regular ones.

---

<div class="post-metadata">

**Author:** ![pjentsch0](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pjentsch0/32/15148_2.png) [@pjentsch0](https://discourse.julialang.org/u/pjentsch0)\
**Post date:** [September 11, 2020, 6:24am UTC](https://discourse.julialang.org/t/get-type-containing-the-types-of-a-set/46304/10 "2020-09-11T06:24:39Z")

</div>

I did test it, and the performance is the same.

And yes, it’s a MWE.
