The type system can get confusing at times. So thanks for the question which got me to learn a few things. Good sources I’ve found:
https://docs.julialang.org/en/v1/manual/types/#man-typet-type
and
As for the specific cases:
Here it is important to note Julia abstract types are invariant, which means:
julia> Vector{Float64} <: Vector{Real}
false
even though Float64 <: Real
. In this example:
N0f8 <: Normed{U} where {U} # true. but...
N0f8 == Normed{U} where {U} # false
which is the same situation as earlier with Float64
and Real
.
Next,
Omitting a parameter T
is the same as adding a {T}
to where
clause, and thus:
( Normed{U} where {U} ) == ( Normed{U,T} where {U,T} ) # true
The above can be rewritten as:
Matrix{RGB{N0f8}} <: Matrix{RGB{Normed{U,T}}} where{U <: Unsigned,T}
N0f8
is an alias to Normed{UInt8, 8}
and so we can rewrite:
Matrix{RGB{Normed{UInt, 8}} <: Matrix{RGB{Normed{U,T}}} where{U <: Unsigned,T}
Again by invariance this is false.
The next case:
is false because the type of value before isa
is not the type after isa
, in fact it is the other way around and:
julia> Matrix{RGB{N0f8}} isa Type{Matrix{RGB{Normed{UInt8, 8}}}}
true
In general T isa Type{T}
and Type{T}
is the type-of-the-type. This is useful to force parameters of parametric functions to be types (see the references at the top).
Lastly, getting back to first case:
The {<: type} where {...}
notation is syntactic-sugar for {T} where {..., T <: type}
. Armed with this knowledge rewriting the second term gives:
Matrix{<:RGB{<:Normed{U}}} where {U<:Unsigned} ==
Matrix{S} where {U <: Unsigned, S <: RGB{T} where {T<:Normed{U}}}
Now we can more easily see that:
Matrix{RGB{N0f8}} <:
Matrix{S} where {U <: Unsigned, S <: RGB{T} where {T<:Normed{U}}}
since S = RGB{N0f8}
and
indeed S <: RGB{T} where {T<:Normed{U}}
because RGB{N0f8} <: RGB{T} where {T<:Normed{U}}
with T = N0f8
because N0f8 <: Normed{U}
by N0f8 = Normed{UInt8, 8}
and Normed{UInt8, 8} <: Normed{U}
with U = UInt8
and Normed{UInt8, 8} <: Normed{UInt8}
by missing parameters considered “free” so Anytype{S,T} <: Anytype{S}
.
It’s all clear as mud… hopefully this discussion diluted this mud a bit