I would like to call the constructor of several parametric families of types efficiently, while only having access to a concrete instance of a type. Also, I am trying to avoid having to write a separate method for each family.
For instance, given x::A{T}, I would like to call the constructor A, and not A{T}.
julia> abstract type B end
julia> struct A{T} <: B
field
end
julia> struct C <: B end
julia> A() = A{String}("hello")
A
julia> A{Int}(1) |> typeof |> supertype |> subtypes |> y -> filter(x -> x <: A, y)[1]()
A{String}("hello")
That is
function constructor(x::F) where F
types = subtypes(supertype(F))
return types[findfirst(x -> F <: x, types)]
end
But I do have to say, this doesn’t feel right to do. What’s your usecase beyond wanting to do this to save some methods? This strangely enough feels like a factory pattern and I can’t quite imagine how you’d end up with that architecture using julia in the first place.
I am working on a module with a number of parametric types. Instances of these types can further be combined in arbitrary ways using an algebra that is defined on them. All types have a parametric type which corresponds to the type of the number field on which they are defined. This is similar to the first type parameter in Julia’s arrays.
Given such a composite type with an associated field type, I need to construct instances with the same hierarchical structure (based on the algebra) but a different field type.
I would think that building a separate method for each family remains the most idiomatic solution. This is more or less what similar does, for example.
That being said, if you really want a fully generic implementation, something like this might work:
I am tending towards using meta-programming for each family then. There are too many types to write this by hand. Depending on ones taste, that might still rely on a lot of internals. It will probably be the most performant solution though.