Type Parameterization of Elements based on `FixedPointNumber.jl` in a Function

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 :stuck_out_tongue_winking_eye:

1 Like