Code:

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

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