# Why NTuple{2, Ref{Int}} <: NTuple get false?

Code:

``````julia> NTuple{2, Int} <: NTuple
true

julia> NTuple{2, Ref{Int}} <: NTuple
false

julia> (NTuple{2, T} where T) <: NTuple
true
``````

`Ref` is an abstract type - you’re probably looking for `RefValue`:

``````julia> NTuple{2, Base.RefValue{Int}} <: NTuple
true

julia> Ref(1) |> typeof
Base.RefValue{Int64}
``````

Alternatively, if you want to be able to have an `NTuple` of any reference type that’s referencing an `Int`, you can use this:

``````julia> NTuple{2, <:Ref{Int}} <: NTuple
true
``````

This specifies that the elements of the tuple have to be subtypes of `Ref{Int}`.

2 Likes

Same as above question. I am a bit of confusing the following:

``````julia> NTuple{2, Integer} <: NTuple{2, T} where T<:Number
false
``````

I know Integer is an abstract and Integer <: Number. What I am reasoning are : the `T` in above code can be any type including abstract type Integer, so above comparing result should be true!

Thank you!

Julia types are invariant, not covariant - see here for more information:

https://docs.julialang.org/en/v1/manual/types/#man-parametric-composite-types

3 Likes

The reason for this particular behavior is often referred to as the diagonal rule. It says that for a tuple type to be a subtype of `Tuple{T, T} where T`, `T` always has to be a concrete type. This is the reason why you can write `f(x::T, y::T) where {T} = ...` to dispatch only on the case where `x` and `y` are of the same type.
I was not aware that this applied to `NTuple` as well, good to know!
Yes, `NTuple` is just an alias for `Tuple{Vararg{T, N}} where {N, T}`.