Suppose I have a base type, which is abstract:
SuperType{T, S, T} = Tuple{T, S, T} where T <: Real where S <: AbstractString
Indeed SuperType can be used for type assertion successfully:
(1.0, "hello", 1.0)::SuperType #> OK
(1.0, "hello", 1)::SuperType #> Error
Now I try to define a concrete type as a subtype of Supertype:
SubType = SuperType{Int, String, Int}
But it fails:
TypeError: in Type, in S, expected S<:AbstractString, got Type{Int64}
I suspect this is somehow related to what are the innermost parameters and what are the outermost
because of the following results:
Following is OK
Tuple2{S,T} = Tuple{S,T} where T<:Real where S<:String
Tuple2{String, Int}
But following produces TypeError: in Type, in T, expected T<:Real, got Type{String}
Tuple3{S,T} = Tuple{S,T} where S<:String where T<:Real
Tuple3{String, Int}
I wonder what principle can explain all these behaviors coherently and how I define SubType as intended. It would be great if the document adds this corner case to improve understanding.
=============================================================================
EDIT:
I 've just realized what mistake I made. There are only two type variables T and S but I specified three in defining a concrete subtype. Also, although not explicitly stated in the document, it is evident by experiment that the innermost type variable should come first. So the correct way is
SubType = SuperType{String, Int}