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!

Please help me to understand why result is false!

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

Thanks for your comment.

Tuples are the exception here though. Tuples in Julia are indeed covariant.

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.

5 Likes

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}.

2 Likes