Tuple type don't inherit as expected

just did some experimentations with Tuple types. Take the following example

d = Dict{Int, Int}
d_unionall = Type{T} where T <: Dict
u = Union{String, Int}
u_unionall = Type{T} where T>:String
isa(d, d_unionall)  # true
isa(u, u_unionall)  # true

then the respective Tuple combination of both does not work

isa((d, u), Tuple{d_unionall, u_unionall})  # false :-( 

EDIT: subtyping works like expected

Tuple{Type{d}, Type{u}} <: Tuple{d_unionall, u_unionall}  # true :-)

anyone an idea what is going on here?

julia> isa((Int,), Tuple{Type{Int}})
false
julia> isa.((Int,), (Type{Int},))
(true,)
1 Like

The issue you are facing is the same as

julia> (Float64, ) isa Tuple{Type{<:AbstractFloat}}
false

I don’t think you can use Type except in the outermost position.

You can use a Tuple type and form the Union outside, eg

julia> Tuple{Float64, Int} isa (Type{Tuple{T,S}} where {T <: AbstractFloat, S <: Integer})
true
2 Likes

thanks a lot!

just misunderstood how isa works obviously

still there is confusion on my side.

Why is the following not working?

julia> (Int, String) :: Tuple{Type{Int}, Type{String}}
ERROR: TypeError: in typeassert, expected Tuple{Type{Int64},Type{String}}, got Tuple{DataType,DataTy
pe}

Sorry for reviving this ancient thread, but I just stumbled upon this question on the search for something else and just would like to know what’s going on in the example by @schlichtanders :sweat_smile:

The answers so far didn’t really explain the reasons for the behavior.

Is this behavior expected (checked in Julia 1.8 and 1.9)?

julia> (Int,) isa Tuple{Type}
true

julia> (Int,) isa Tuple{Type{Int}}
false

My understanding so far was that X isa T implies that (X,) isa Tuple{T}. The example shows that this is not true, and it seems related to how Type works. But it feels like the implication should be true, given that Tuple is used to represent function signatures and e.g. the following works

julia> foo(t::Type{Int}) = println(t);

julia> foo(Int)
Int64

julia> foo(Float64)
ERROR: MethodError: no method matching foo(::Type{Float64})

More specifically, the method signature doesn’t match a tuple with the actual inputs to the function call

julia> (foo, Int) isa only(methods(foo)).sig
false

But it does (as far as I can tell) for “normal” signatures involving no Type:

julia> baz(x::Int) = 2x;

julia> (baz, 1) isa only(methods(baz)).sig
true

What makes Type special in this regard?

1 Like