Why is Matrix{Float64}<:Matrix{Number} false?
search type invariance. TLDR is that they need different memory representations.
It also follows from the rules of concrete subtyping. Matrix{Number} is a concrete type that can be instantiated, and concrete types cannot have subtypes.
Try this:
Matrix{Float64} <: Matrix{<:Number}
See also Types · The Julia Language
In particular:
In other words, in the parlance of type theory, Julia’s type parameters are invariant, rather than being covariant (or even contravariant). This is for practical reasons: while any instance of
Point{Float64}may conceptually be like an instance ofPoint{Real}as well, the two types have different representations in memory:
- An instance of
Point{Float64}can be represented compactly and efficiently as an immediate pair of 64-bit values;- An instance of
Point{Real}must be able to hold any pair of instances ofReal. Since objects that are instances ofRealcan be of arbitrary size and structure, in practice an instance ofPoint{Real}must be represented as a pair of pointers to individually allocatedRealobjects.The efficiency gained by being able to store
Point{Float64}objects with immediate values is magnified enormously in the case of arrays: anArray{Float64}can be stored as a contiguous memory block of 64-bit floating-point values, whereas anArray{Real}must be an array of pointers to individually allocatedRealobjects – which may well be boxed 64-bit floating-point values, but also might be arbitrarily large, complex objects, which are declared to be implementations of theRealabstract type.
Could you elaborate on this a bit more? I am confused by the syntax of Matrix{<:Number}
Invariance of type parameters means that e.g. Matrix{Float64} is not a subtype of Matrix{Number}, even if Float64 is a subtype of Number. However, there exists “wildcard” type parameters in the form of UnionAll types. Typically such a UnionAll type is written with the where clause: Matrix{T} where T<:Number. It is an abstract type which has all Matrix{T} as subtypes where T is a subtype of Number. A short form is Matrix{<:Number}, which can be used if you do not need to use the type variable T elsewhere.
julia> dump(Matrix{<:Number})
UnionAll
var: TypeVar
name: Symbol #s3
lb: Union{}
ub: Number <: Any
body: Array{var"#s3"<:Number, 2} <: DenseArray{var"#s3"<:Number, 2}
julia> dump(Matrix{T} where T<:Number)
UnionAll
var: TypeVar
name: Symbol T
lb: Union{}
ub: Number <: Any
body: Array{T<:Number, 2} <: DenseArray{T<:Number, 2}
Beat me to it ![]()
This was going to be my response:
As others have mentioned, Matrix{Number} is a concrete type, and one concrete type cannot subtype another concrete type.
Matrix{<:Number} is a union of types, and is shorthand for Matrix{T} where {T<:Number}.