This question builds on What is difference between Type{T} and T - #16 by Henrique_Becker
Are there any objections to the definition below?
Based on the following two quotes from Types · The Julia Language
One particularly distinctive feature of Julia’s type system is that concrete types may not subtype each other: all concrete types are final and may only have abstract types as their supertypes.
When the type is abstract, it suffices for the value to be implemented by a concrete type that is a subtype of the abstract type.
Definition: Object x is an instance of the abstract type y if, and only if, the concrete type t_x of x and the value v_y of y satisfy t_x <: v_y.
Note that, according to this definition, Type is an instance of itself because
julia> typeof(Type)
UnionAll
julia> UnionAll <: Type
true
Moreover, this definition works with examples like Type{Float64}. It is an instance of Type because typeof(Type{Float64}) = DataType and DataType <: Type both hold.
But UnionAll is not an instance of itself
julia> typeof(UnionAll)
DataType
julia> DataType <: UnionAll
false
Indeed, via the same argument, no type in the chain (Int64, Signed, Integer, Real, Number) is an instance of itself.
Whilst I am comfortable with the above, the Ptr provides a potential counterexample because, according to the manual it has “instances” such as Ptr{Int64} and Ptr{Float64}. But
julia> typeof(Ptr{Float64})
DataType
julia> DataType <: Ptr
false
and
julia> isa(Ptr{Float64},Ptr)
false
Personally, I like definition at the top of this post as I can imagine applying it in the field. There are two ways to rescue it:
- say that
Ptris not an abstract type. Is this reasonable? If so, then is it concrete, or can parametric types be neither abstract, nor concrete? - say that
Ptr{Int64}is not an instance ofPtr. This would fit the observation thatPtrhas no subtypes, but not the observation thatPtr{Int64} <: Ptrholds. (I am putting this latter contradiction in a separate topic.)