Get new type with different parameter

How do I get a type with a different parameter? Let’s say I have some T where T<:SomeType{P} and I want the type SomeType{Q}. I can’t just do T{Q} because T is a concrete type.

julia> struct SomeType{P} end

julia> switch(::Type{SomeType{P}}, ::Type{T}) where {P,T} = SomeType{T};

julia> switch(SomeType{Int}, Float64)
SomeType{Float64}

The problem is I don’t know it’s going to be SomeType. I just know it’s a type with one parameter and I want to change that parameter.

Sorry to say that this is not supported by Julia’s type system and according to those in the know, it is not a “well defined” operation.

2 Likes

Have a read through:
https://docs.julialang.org/en/v1/manual/methods/#Extracting-the-type-parameter-from-a-super-type-1

The thing is, that parameters might change place, or don’t exist (see the BitVector example). Thus, it is generally not a good idea to do this. If you still want to do it, you probably want a generated function:

julia> @generated function newT(::Type{T}, ::Type{TT}) where {T,TT}
           getfield(parentmodule(T), nameof(T)){TT}
       end
newT (generic function with 2 methods)

julia> newT(Array{Int,2}, Float64)
Array{Float64,N} where N

adapted from https://github.com/JuliaObjects/ConstructionBase.jl/blob/b5686b755bd3bee29b181b3cb18fe2effa0f10a2/src/ConstructionBase.jl#L25.

3 Likes

Thanks for this. Arrays are actually my use case. I wanted to implement the SomeElType.(::MyArrayType{DifferentElType}) syntax for changing the eltype of the array that my arraytype is wrapping since that’s required to work with Optim.jl. I didn’t want to look through my BroadcastStyle arguments .args when I had all the information I needed in the types. After thinking about it a little bit more, I realize why this isn’t generally supported in the language. Since my array is always going to be the first element, it wasn’t as bad as I thought to just grab the first .arg and work with that directly.

1 Like