# Parametric types as subtypes of the type parameter

I want my parametric types to be subtypes of the type parameter.

Consider a wrapper for floats:

``````struct wrapper{T} <: T where {T <: Union{Real}}
bar::T
end
``````

This example works fine. Now consider making the type `T` to be a subtype of `Union{Real,Complex}`. This throws an

invalid subtyping in definition of

Since `Real` and `Complex` are subtypes of `Number`, something such as

``````struct wrapper{T<: Union{Real, Complex}} <: Number
bar::T
end
``````

would be a possible solution for most cases.

However, this would be a quick fix and would defeat to the purpose of the parametric type to be a subtype of the type parameter. How does one achieve this?

1 Like

I don’t think it’s possible to make a subtype relation parametric; even in your first example, `Union{Real}` evaluates to just `Real`, so the `supertype` of any instance will always be `Real`, like

``````julia> wrapper(1)
wrapper{Int64}(1)

julia> supertype(typeof(ans))
Real

julia> wrapper("hey")
wrapper{String}("hey")

julia> supertype(typeof(ans))
Real

julia> wrapper(1.0)
wrapper{Float64}(1.0)

julia> supertype(typeof(ans))
Real
``````

Maybe you can elaborate the use-case and why having the parametric subtype relation seems to be important?

I am extending the ForwardDiff package to work with R –> C functions (currently it is limited to R –> R functions).

This requires the use of Dual Numbers, originally defined as

``````Dual{T,V<:Real,N} <: Real
``````

where `V` is the “machine” type of the number (e.g., Float64) and T and N are not really important in this discussion.

I believe an extension to complex numbers would be correct with a redefinition such as

``````Dual{T,V,N} <: V where {V <: Union{Real, Complex}}
``````

allowing the Dual number to either be Real or Complex but this seems to result in a

invalid subtyping in definition of

error.

Why don’t you just use a function from R to R^2 for the derivative and then convert to a complex?

Eg see the realify function in IntervalRootFinding.jl

1 Like

Because I don’t think that should be the way to solve the problem. There have been issues reported since 2016 hinting for support for R –> C function differentiation and I thought I would take upon the task myself.
The end goal is to differentiate eigenvalues (hence R^n –> C^{m x m}) so I would stay away from such conversions, no?

But we digress. The question at hand is how to make a parametric type be a subtype of the type parameter with Unions.

What you are asking for is not possible, because it would make the direct supertype of the declared type ambiguous.

To see why this is the case, consider

``````struct Wrapper{T<:Number} <: Number
x::T
end
``````

Now, clearly `Number` is a supertype of `Wrapper{Float64}`. However, `Wrapper` (which you should think of as an abstract type) is also a supertype of `Wrapper{Float64}`. What is the supertype of `Wrapper`? Well, in this case `Number` is still a supertype of `Wrapper`, but if we had made it parametric as you are suggesting, it would be undefined. Julia does not allow this, since in Julia `T` is always a supertype of `T{U}`. This isn’t done arbitrarily, in fact this is one of the most common method signatures (e.g. `::AbstractVector` is a very common type of function argument to see).

I’m not quite sure what you’re trying to do, but I suspect that pattern that would be best for you would be what I showed above. (Also note that the reason your first example worked without error was because it’s equivalent to what I showed above.) This still gives you a lot of flexibility, and you can still do it with arbitrarily complicated `Union` types.

I don’t think it is possible to make a type subtype of `Complex` since it is not an abstract type, so the `Complex` will break the subtyping anyway, even it is not in a union.

Could you make a `Complex{Dual}` instead of a `Dual <: Complex`?

1 Like

You don’t need to make it a subtype of Complex.