Get the type parameters of a parametric type

I have an instance of a parametric type. Is it possible to somehow retrieve the type parameters for this instance?

E.g. for ```julia
struct MyStruct{T}
x::T

function MyStruct(x)
    return new{typeof(x)}(x)
end

end

ms = MyStruct(1.0)
typeof(ms)

I'd like to know the type parameter `Float64`.

I believe you have to define the eltype for MyStruct. In this case:

Base.eltype(::Type{MyStruct{T}}) where T = T

This will allow you to get the parameter type:

julia> ms1 = MyStruct(1.0)
MyStruct{Float64}(1.0)

julia> eltype(ms1)
Float64

julia> ms2 = MyStruct(1)
MyStruct{Int64}(1)

julia> eltype(ms2)
Int64
1 Like

eltype should only be defined for containers/collections:

help?> eltype
search: eltype valtype keytype fieldtype oftype fieldtypes supertype subtypes code_typed

  eltype(type)

  Determine the type of the elements generated by iterating a collection of the given
  type. [...]

It’s not a generic “get a type parameter” function.

That kind of functions doesn’t (and can’t, in general) exist, because what exactly a type parameter means to the type depends on that type. It doesn’t generalize.

5 Likes

Perhaps:

get_parameter_type(::MyStruct{T}) where T = T
4 Likes

Ah good point. I guess I’m really use to working with collections. @sylvaticus’s suggestion makes more sense to avoid type piracy then.

I guess the bigger question to @Gaussia is why do you need the parametric type?

2 Likes

If MyStruct is a type that you own, then you could just get the type of the field x:

ms = MyStruct(1.0)
typeof(ms.x)
1 Like

Consider instead the following:

julia> struct MyStruct{T}
       x::T
       end

julia> ms=MyStruct{Union{Float64, Missing}}(1.0);

julia> typeof(ms.x)
Float64

julia> typeof(ms).parameters[1]
Union{Missing, Float64}

julia> extract_the_T(::MyStruct{T}) where T = T
extract_the_T (generic function with 1 method)

julia> extract_the_T(ms)
Union{Missing, Float64}

PS. On current master, extract_the_T2(ms) = typeof(ms).parameters[1] does constant propagate. This might not const-prop on earlier julia versions – test it in order to avoid inference failures.

1 Like

I’m pretty sure that .parameters is an internal field, so not realiable. Extracting the type parameter in a dedicated function through the parameters there is IMO better, because it’s more stable & doesn’t rely on internals.

5 Likes

Oops, good point.

Indeed this is the most relevant question. Specifically, if the user needs to query a value or a type for something, which may be a type (eg eltype), this should be exposed via a function, and the fact that this may be encoded in a parametric type is an implementation detail.

4 Likes

So, in this case MyStruct was just an example I added to make what I want to do more clear, figured there probably was an easy way for this.

I want to apply this to a structure I do not actually own. Basically, there’s this DiffEq composite structure which typeof is reaaaaaaly long. To try and figure out what it actually is, I wanted to look at the parametric types on by one.

1 Like

I see — this is for code exploration only. In that case, I would recommend dump, and of course reading the source code, but typeof(T).parameters is fine too.

2 Likes

That worked great, thanks a lot!

1 Like