What does `<:` as a type parameter mean?

julia> Array{<:,2}
Matrix{<:} (alias for Array{<:, 2})

julia> Array{<:,2} === Array{<:Any,2}
false

julia> Matrix{<:} isa UnionAll
false

I wonder if Matrix{<:} means anything?

I think even while === returns false, it’s equivalent in use to the expression with <:Any because all types are <: Any and an empty UnionAll can contain any type.

No, this specifies a Matrix with elements of type <:, which can’t be instantiated unless you shadow the definition in Base:

julia> struct <: end

julia> f(x::Array{<:,2}) = x
f (generic function with 1 method)

julia> f(fill(<:(), 2, 2))
2Ă—2 Matrix{<:}:
 <:()  <:()
 <:()  <:()

There are no checks to ensure that the first type parameter of Array actually is a type, so Array{2,3} is also “valid”.

3 Likes

To complement @pfitzseb’s answer, I think Matrix{<:} is similar to Matrix{sin}: in both cases an existing function is used as type parameter. As the doc says, any isbits value can be used as type parameter, and functions are isbits values.

3 Likes