I don’t understand the following behavior:
julia> typeof((a = (b = 1,),)) <: NamedTuple{(:a,), Tuple{<:NamedTuple}}
false
julia> typeof((a = (b = 1,),)) <: NamedTuple{(:a,), Tuple{NT}} where {NT <: NamedTuple}
true
I don’t understand the following behavior:
julia> typeof((a = (b = 1,),)) <: NamedTuple{(:a,), Tuple{<:NamedTuple}}
false
julia> typeof((a = (b = 1,),)) <: NamedTuple{(:a,), Tuple{NT}} where {NT <: NamedTuple}
true
This is due to two confusing things:
Tuple
is covaritant w.r.t its type parameters, whereas NamedTuple
is invariant.A{B{C}} where {C <: D}
is different from A{(B{C} where {C <: D})}
. In the former, B
is treated as a TypeVar
, so it’s equivalent to A{<:B{C<:D}}
.So, let’s look at (a = (b = 1,),)
.:
NamedTuple{(:a,), Tuple{NamedTuple{(:b,), Tuple{Int}}}}
UnionAll
type NamedTuple{(:a,), <:Tuple}
.
Tuple{NamedTuple{(:b,), Tuple{Int}}}} <: Tuple
NamedTuple{(:a,), Tuple}
, which is what your first line queries, because NamedTuple
is invariant.Your second line has NamedTuple{(:a,), Tuple{NT}} where {NT <: NamedTuple}
.
where
is outside the outer parenthesis, there where
applies to the outermost NamedTuple
- in other words, it makes the NamedTuple
a UnionAll
NamedTuple{(:a,), <:Tuple{<:NamedTuple}}
. And this is clearly a correct supertypeNamedTuple{(:a,), (Tuple{NT} where {NT <: NamedTuple})}
is NOT a supertype of the given name dtuple, because the where
is inside the outer parenthesisThanks for the quick reply and the explanation regarding UnionAll
types