'Correct way to wrap and dispatch on complicated types
TLDR: What is the safest and simplest way to wrap specific instances of some complicated type NotMyType (with many type parameters) into MyType such that no performance is lost when dispatching on instances of MyType and the type itself Type{MyType}?
I will try to give an example of what I am trying to achieve here.
Suppose I intend to wrap a concrete type GenericType{N, A} <: AbstractGenericType{N} where A can either be Type1 or Type2 and N is some value type. This type is provided by some package Foo.jl. I wish to create a wrapper PhysicalType which a subset of say GenericType{3}; that is every PhysicalType is a GenericType{3}, but not every GenericType{3} is a PhysicalType. I intend to dispatch on PhysicalType, otherwise I would have just made a specific constructor.
To me, the most sensible way of specifying PhysicalType would be something like
struct PhysicalType{T<:GenericType{3}}
type::T
end
Then I can forward all the GenericType methods to PhysicalType using something like the @forward macro from MacroTools.jl.
However, I also need to forward a function say Foo.func() who's argument is of type Type{<:GenericType}. The function Foo.func has two methods defined in Foo that look something like,
Foo.func(Type{<:GenericType{N, Type1}} = Type1
Foo.func(Type{<:GenericType{N, Type2}} = otherfunc(Type2)
I want this function to behave exactly the same for PhysicalType as it does for GenericType, so I would do something like:
function Foo.func(::Type{<:PhysicalType{T}}) where {T<:GenericType{3}}
return Foo.func{T}
end
My question is, there seems to be a lot of redundant information here. Do I need to specify the type of T as PhysicalType only ever wraps instances of GenericType{3}? I also do not want a method defined for every possible instance of T, that seems pointless. I only need two methods, one where T==GenericType{3, Type1}, and another where T==GenericType{3, Type2}.
Would it make more sense to just do something simple like:
function Foo.func(::Type{<:PhysicalType{T}) where T
return Foo.func(T)
end
I do not wish to provide the compiler with redundant information (I also do not want to write it if I don't have to), but it is important that I inherit all the performance associated with the methods on GenericType. Really I just want PhysicalType to behave identically to GenericType, but also have the opportunity to dispatch on PhysicalType if need be. What is the canonical or most "Julian" way of achieving this?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
