Why can't i write such a function?

function get_typparam(::Type{X{Q1,Q2,Q3}}) where X where {Q1,Q2,Q3}
           [Q1,Q2,Q3]
 end

ERROR: TypeError: Type{…} expression: expected UnionAll, got TypeVar

Thanks

is X a type? You might be confusing the syntax x <: Int from x <: Type{Int}

Allowing that could make dispatch undecidable.

1 Like

Not sure if that’s useful but I was trying to do similar gymnastics, asked a question on stackoverflow where it was kindly explained to me that something like this is the neat way of recovering the type of a struct:

struct Foo{T<:Real}
  x::T 
end
bar(f::Foo{T}) where T = T  
bar(Foo(2.0)) # --> Float64
bar(Foo(2)) # --> Int

It can probably be done better but I thought it helped clarify types & multiple dispatch. (Apologies if that’s not at all what you’re trying to do)

I think X as a fully unrestricted type is not possible,
If X is the subtype of some abstract type that has the type parameters you are interested in you can

You can do something like
https://github.com/JuliaText/Embeddings.jl/blob/65b658865e476981c4c74988018274e77dcd0b03/src/Embeddings.jl#L32-L36

So you can do, if X is always a subtype of AbstractFoo{Q1,Q2,Q3}

function get_typparam(::Type{X}) where {X <: AbstractFoo{Q1,Q2,Q3}} where {Q1,Q2,Q3}
           [Q1,Q2,Q3]
end

I think.
(not tested)

You also get the type parameters of a type by inspecting the type variable itself:

function type_params(x::Type)
    t = Base.unwrap_unionall(x)  # unpack a unionall in case not all type parameters are specified
    return (t.parameters...,)    # convert to a regular tuple
end

# test case
struct X{A,B,C} end

x1 = X{Int}
x2 = x1{Real}
x3 = x2{3}

This prints

Main> type_params(x1)
(Int64, B, C)

Main> type_params(x2)
(Int64, Real, C)

Main> type_params(x3)
(Int64, Real, 3)
1 Like

I did something like this once, that worked as well, not sure if this is what you’re trying to do though :smiley:

eltypes(::Type{Cache{T, Dim, CC, CF}}) where {T, Dim, CC, CF} = (T, Dim,CC, CF)
eltypes(p) = eltypes(typeof(p))