Three confusing things are happening here:
- In Julia, types are values and values are types. We can’t draw clear distinctions between them. All types are values that are instances of
DataType(well, almostUnion{}strikes again!). But that means we couldn’t dispatch on a type because they are allDataTypes. So… Typeis a unique, special-cased type that allows for sharpening type fields.It is extremely important to dispatch and such, but it does cause a violation of the type system’s rules which–I believe–leads to the friction you’re experiencing. Specifically, while each type is an instance of the concrete type. Edit: see my comment below, this is not correct.DataType, it is ALSO an instance of the concrete typeType{T}(for some T). This is normally impossible (an instance can only be of one concrete type)Anyis the top of that type system. By definition, all types are subtypes ofAny. ButAnyis also an instance ofDataTypebecause types are just values. Not too weird, but it does yield funny things like:
julia> typeof(Any) <: Any
true
Your taxonomy of types doesn’t work because it presupposes that there are different kinds of types. There are not. Julia has a type system which describes the super- and sub-type relationships between all types, without drawing distinctions between those types.
The “issue” that
Isn’t an issue for the soundness of the system. Walking through it:
Int isa Type{Int}– as we’ve addressed, this is the odd case.Type{Int} <: DataType– This is true because in a deep wayType{T} where T === DataType, so this is like sayingType{Int} <: Typewhich is true.DataType <: Type– All types, includingDataType, areTypes. Specifically,DataType isa Type{DataType}.Type <: Anythis is axiomatic to the Julia type system.
I also don’t understand where your claim that:
comes from in the docs? Can you clarify the contradiction you’re seeing? Based on my reading of your code example above that claim, I don’t see an issue.
DataTypeis the type of all types. SoDataType(being a type) is an instance ofDataType.- Also,
T <: Tis true for allTwhereTis a type. SoDataType <: DataTypemust be true. DataTypeis an unparametrized type that has instances (all the other types), so it behaves like any concrete type.
Edit: Thinking about this more – I’m actually wondering if it’s more like DataType is the real special case because it is basically Type{T} where T in a trenchcoat pretending to be concrete even though it’s a UnionAll? I don’t know. Someone who knows more Type Theory will have to weigh in there ![]()