This is not special. Number
is also not a concrete type, but 1 isa Number
is true…
Perhaps the wording “has an instance” is confusing here? It is mentioned in the docs (same quote that @samuel mentioned originally, I’m just repeating it here for clarity) that
For each type T
, Type{T}
is an abstract parametric type whose only instance is the object T
.
There seems to be an understanding that only concrete types can have instances. but this is just not true.
The same docs page also mentions for example
the ::
operator is read as “is an instance of”. It can be used anywhere to assert that the value of the expression on the left is an instance of the type on the right. When the type on the right is concrete, the value on the left must have that type as its implementation
Of course any type can be on the right-hand side of ::
, including abstract types. One example being Any
, for which it is stated that
When no supertype is given, the default supertype is Any
– a predefined abstract type that all objects are instances of and all types are subtypes of
So “having instances” is clearly possible for abstract types as well as abstract [EDIT: concrete] types.
As to the original question of @samuel , it does seem weird that both of these are true: [EDIT: The second one is not confusing here, just that both are true at the same time.]
Type{Int} <: DataType
Type{Int} isa DataType
The first one also seems confusing to me at first glance, but in the “set theory” picture that the REPL docstring of <:
also gives
Subtype operator: returns true if and only if all
values of type T1 are also of type T2.
it makes sense. All values (instances) of Type{Int}
, which is only Int
, are also values (instances) of DataType
since all concrete types are of type DataType
(I presume that’s why its called DataType
, since it directly refers to data and has to have some concrete memory layout, some numer of bytes required to represent the values etc. – but then again, also abstract types are of type DataType
, e.g. Number
if they are not unions or parametric).
But by this logic, also these have to be true:
DataType <: Type
(every possible value of DataType
is in fact a type, so it is also a possible value of Type
UnionAll <: Type
(every value of UnionAll
are essentially the parametric types, so again types)
Union <: Type
(a union of any types is still a type, so if you write Union{Int, String}
that itself is a type in the sense of “a type is a bag of all its possible values”)
- I have no real clue what
Core.TypeofBottom
actually does…
I think the answer to the question 3 from the original post is yes:
- Are all types of some type that is listed above?
All concrete and “non-union or parametric” types are of type DataType
, all parametric types are UnionAll
and what’s left are Unions
I guess.
Question number 4 is also confusing me, but I guess to get all the desired relations between Any
, DataType
, etc. it is necessary that Type{Int} <: DataType
is true, but still DataType
is considered a concrete type, since it has values that have a concrete memory layout etc.
This really does sound like a contradiction, but I think it comes down to the “fuzzyness” that @mrufsvold mentioned
In Julia, types are values and values are types. We can’t draw clear distinctions between them