# Why? isa(\[(x,1),(y,1)\], Array{Tuple{Stuff,Number},1}) = false

**URL:** https://discourse.julialang.org/t/why-isa-x-1-y-1-array-tuple-stuff-number-1-false/55777
**Category:** General Usage
**Created:** [February 22, 2021, 1:49pm UTC](https://discourse.julialang.org/t/why-isa-x-1-y-1-array-tuple-stuff-number-1-false/55777 "2021-02-22T13:49:54Z")
**Posts on this page:** 1
**Showing post:** 6

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [February 22, 2021, 4:52pm UTC](https://discourse.julialang.org/t/why-isa-x-1-y-1-array-tuple-stuff-number-1-false/55777/6 "2021-02-22T16:52:04Z")

</div>

[Covariance and etc.](https://en.m.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)) mean so many things outside computer science that it took me a while to get what people where saying here.

I prefer to explain, probably not as comprehensively, but at least simply, by noting that:

First, we have to differentiate two things:

a) An array that _can only_ contain numbers of type `Float64`  
b) An array that _can_ contain real numbers of different types (mixed `Float64` and `Int64`, for example).

Vectors of type (b) are not a subtype of vectors of type (a), of course, because vectors of type (a) cannot contain an `Int64`, for example. This is clear and translates to:

```julia
Vector{Real} <: Vector{Float64} == false

```

Less clear is that an array of type (a) is also not a subtype of an array of type (b). This is because an array of type (a) _has a constraint_ that vectors of type (b) do not. Thus, a vector of type (a) is not a subtype of vectors of type (a), and this translates to the more unnatural

```julia
Vector{Float64} <: Vector{Real} == false

```

Second, the usual confusion is that `Vector{Real}` is intuitively thought as _all types of vectors that contain real numbers_. Well, this is the wrong way of reading that. As pointed above, `Vector{Real}` is the type of a concrete vector that _is able_ to contain any type of real number. Thus, this does not include the vectors that _cannot_ contain `Int64`s, for instance.

We need a notation for the _set of vectors_ that may contain real numbers, restricted or not by type. The notation might sound arbitrary, but we need one, and it is `Vector{<:Real}`. Since this is the notation that encompasses different types of vectors, it is an _abstract type_\*, contrary to the other two above, which are _concrete types_.

No actual vector is, therefore, of type `Vector{<:Real}`. To be very redundant:

```julia
julia> typed(Real[1,2.0,π,Float32(7)]) == Vector{<:Real}
false

```

But all vectors that contain only real numbers, are subtypes of `Vector{<:Real}`:

```julia
julia> typeof(Real[1,2.0,π,Float32(7)]) <: Vector{<:Real}
true

julia> typeof(Int[1,2,3]) <: Vector{<:Real}
true

```

When one uses `Vector{<:Real}` we are referring a _set_ of types. The final confusion that may arise, is, for example, that:

```julia
julia> typeof(Int64[1,2,3]) == Vector{<:Int64}
false

```

This is `false` because `Vector{<:Int64}` is the _set_ of types of vectors that contain only `Int64` numbers. It is not a concrete type of vector, even if the set contains only one type which is `Vector{Int64}`.

Of course:

```julia
julia> typeof(Int64[1,2,3]) <: Vector{<:Int64}
true

```

\*Strictly speaking, in the Julia language, something like `Vector{<:Real}` is of the `UnionAll` type, which is something in between between a completely abstract type which only serve as nodes in the type tree, and a concrete type which can actually be instantiated. `UnionAll` types do have information on how they should be instantiated, by that information is not complete.

(note: the final form of this post has contributions from others, given below).

---

_[View the full topic](https://discourse.julialang.org/t/why-isa-x-1-y-1-array-tuple-stuff-number-1-false/55777)._
