How to make type parameter for `Tuple` represent both abstract type and concrete type?

julia> t1 = NTuple{2, Real}
Tuple{Real, Real}

julia> t2 = NTuple{2, T} where {T<:Real}
Tuple{T, T} where T<:Real

julia> t1 <: t2
false

julia> t3 = NTuple{2, <:T} where {T<:Real}
Tuple{var"#s1", var"#s1"} where {T<:Real, var"#s1"<:T}

julia> t1 <: t3
false

It seems that the type parameter T cannot be inferred as an abstract type unless I constrain it to be a specific one:

julia> t4 = NTuple{2, T} where {Real<:T<:Real}
Tuple{T, T} where Real<:T<:Real

julia> t1 <: t4
true

Is there a way to let T can be both a concrete type that <: Real and Real? Currently, my workaround is

julia> t5 = Union{t2, NTuple{2, Real}}
Tuple{Real, Real}

julia> t1 <: t5
true

julia> NTuple{2, Float64} <: t5
true

However, it’d be better if I don’t have to use Union. Thanks!!

Hm. This

t1 = NTuple{2, Real}
t2 = Tuple{T1, T2} where {T1<:Real, T2<:Real}
@show t1 <: t2

fulfills the requirement of showing true,

t1 <: t2 = true

but I’m not sure if it is what you are looking for?

Thanks! However, what I want is the common type of all the elements in the Tuple as T so that I’ll be able to go something like NTuple{N, T} where {N, T} where T can be both a concrete type and an abstract type.

Funnily enough in the above context we even have

@show t2 <: t1

yielding

t2 <: t1 = true

so I don’t believe it gets much better than that.

Edit: however, look at this

t1 = StaticVector{2, Real}

t2 = StaticVector{2, T} where {T <: Real}

@show t1 <: t2
@show t2 <: t1

yielding

t1 <: t2 = true
t2 <: t1 = false