Decompose Tuple or Union type into constituents?

Is it possible to iterate over the parameters of a Tuple or Union? Given Tuple{A, B, C, D, E, ...}, is it possible to extract the parameters (A, B, C, D, E, …)?

A partial solution/hack is something like this, for extracting only a single parameter by position:

# Extracts second Tuple parameter in a Tuple type with two elements.
f(::Type{Tuple{S, T}}) where {S <: Any, T <: Any} = T

# Extracts second Tuple parameter.
g(::Type{<:Tuple{<:Any, T}}) where {T <: Any} = T

A related question is: how do I convert an arbitrary tuple type to to a corresponding union, for example Tuple{A, B, C, D} would be converted to Union{A, B, C, D}. Or Perhaps even something like Tuple{A, B, Tuple{C, D}} to the same Union.

I don’t have a real use for this, just being curious.

julia> a = (1, 1.2, "a")
(1, 1.2, "a")

julia> typeof(a).types
svec(Int64, Float64, String)
2 Likes

Interesting, never encountered a SimpleVector before!

They are not something users generally need to use. They are used by the compiler because it’s very useful to have a very simple list type that doesn’t have strict types.

3 Likes

reiterating what @Oscar_Smith said …
There really is no good reason for julia developers to ever do anything with svecs other than convert them to a tuple or, if appropriate, a vector. The svec is not a completed data structure – it does what Base requires of it, and does not do whatever else it might. Their use is a fast track to unexpected occurrences.

Another approach to the proposed function:

function eltypesof(x::T) where {T<:Union{Tuple, NamedTuple}}
   Tuple( typeof(x).types )
end

function eltypesof(x::Type{T}) where {T<:Union{Tuple, NamedTuple}}
    Tuple(x.types)
end

function eltypesof(x::Type{T}) where {T<:NamedTuple}
    Tuple(x.types) 
end

function eltypesof(x::U) where {U<:Union}
   Tuple( Base.uniontypes(x) )
end

eltypesof(::Type{Union{}}) = ()
# or, depending on the intended semantics
# eltypesof(::Type{Union{}}) = Core.TypeOfBottom

It also handles NamedTuples.

1 Like

Why mess about with internal fields and svecs instead of just doing

julia> typeof.(a)
(Int64, Float64, String) 

?

2 Likes

The question as posed is for when only a Tuple type is available as input, not a tuple instance.

1 Like

now do Union

1 Like

Okay, but the accepted answer was on a tuple instance, which is a bit confusing, then.

Or in other words, then assume my answer was a response to this particular line of code, instead of the OP:

Why do this on a tuple?

1 Like

thank you – see the revision above

you can use that as Tuple(unique(typeof.(a)))as long as there is no need to go into sub tuples, which is simply unclear in the question.

I have tested the revised routines for empty and nonempty Tuples and NamedTuples and Unions. Let me know if you find a state I have overlooked.

1 Like