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

Covariance and etc. 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:

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

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 Int64s, 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> typed(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

*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).

7 Likes