Tricky parametric type dispatch

I would like to dispatch a method like this, where T gets the type <: AbstractParticles and the type parameters end up in F and NT.

function Base.union(p1::T{F,NT},p2::S{F,NS}) where T <: AbstractParticles where S <: AbstractParticles{F,NS} where F where NT where NS
    T{F,NT+NS}([p1.particles; p2.particles])
end

This does not work and an error

TypeError: in Type{...} expression, expected UnionAll, got TypeVar

occurs. The following definition is accepted, but it makes T include the type parameters T{F,NT} which I do not want.

function Base.union(p1::T,p2::S) where T <: AbstractParticles{F,NT} where S <: AbstractParticles{F,NS} where F where NT where NS
    @show T
end
julia> union(p,p)
#T = Particles{Float64,1000}

Is there another way to express the former, or to strip Particles{Float64,1000} from the type parameters without using eval?

Edit:
The following works, but feels like a hack

function Base.union(p1::T,p2::S) where T <: AbstractParticles{F,NT} where S <: AbstractParticles{F,NS} where F where NT where NS
    T.name.wrapper{F,NT+NS}([p1.particles; p2.particles])
end

It does not feel like I’m supposed to use the T.name.wrapper

Edit 2:
I can also put the function definition in a loop over the different possible T and @eval the function into existence.

No, you cannot do this in general. This is why similar exists for arrays and you should probably use a similar approach. X-ref:

2 Likes

Hi @baggepinnen :wave:

Out of curiosity, why don’t you want this? After all, T does include parameters F and NT according to your first attempt above.

The accepted definition looks fine to me so I am curious why you don’t like it.

I didn’t want the type parameters included as I would like to modify them, in my case call T{F,NT+NS}.

Thanks for the link, which led me to this section of the manual
https://docs.julialang.org/en/latest/manual/methods/#Building-a-similar-type-with-a-different-type-parameter-1
which is exactly what I would like to do