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 of`Point{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 of`Real`

. Since objects that are instances of`Real`

can be of arbitrary size and structure, in practice an instance of`Point{Real}`

must be represented as a pair of pointers to individually allocated`Real`

objects.The efficiency gained by being able to store

`Point{Float64}`

objects with immediate values is magnified enormously in the case of arrays: an`Array{Float64}`

can be stored as a contiguous memory block of 64-bit floating-point values, whereas an`Array{Real}`

must be an array of pointers to individually allocated`Real`

objects â€“ 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 the`Real`

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

.