# Vector{Int} <: Vector{Real} is false??

Covariance and etc. mean so many things outside computer science that it took me a while to get what people meant when explaining covariance, contravariance, invariance, etc, in the context of Julia type system.

I prefer to explain the relation between the container types, 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:

`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 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

`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> typeof(Real[1,2.0,π,Float32(7)]) == Vector{<:Real}
false
```

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

:

```
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> 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> typeof(Int64[1,2,3]) <: Vector{<:Int64}
true
```

A final note: checking if a concrete type is a concrete type or a subtype of a supertype that contains it can be done with `isa`

:

```
julia> Int[1,2,3] isa Vector{Int}
true
julia> Int[1,2,3] isa Vector{Real}
false
julia> Int[1,2,3] isa Vector{<:Real}
true
```

Note that isa corresponds to `typeof(x) <: T`

, not `typeof(x) == T`

. This makes sense because then `1 isa Number`

, for example, while `typeof(1) == Number`

is `false`

, because `Number`

is an abstract type.

*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: This text was originally posted as a response to this thread, and its final form includes contributions from other people, as indicated in the thread.