# Type compare

**URL:** <https://discourse.julialang.org/t/type-compare/87351>\
**Category:** New to Julia\
**Created:** [September 16, 2022, 6:43am UTC](https://discourse.julialang.org/t/type-compare/87351 "2022-09-16T06:43:46Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [September 16, 2022, 6:43am UTC](https://discourse.julialang.org/t/type-compare/87351/1 "2022-09-16T06:43:46Z")

</div>

As shown blow:

```julia
(Int,10) isa Tuple{Type{Int},Int}
False

```

So, how can I define a `T`,

```julia
function f(x::T) where T <: Tuple{Type{Int},Int}
end

```

Of course, this would work `T <: Tuple{DataType,Int}`, but it is limited. Is there other ways?

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [September 16, 2022, 8:11am UTC](https://discourse.julialang.org/t/type-compare/87351/2 "2022-09-16T08:11:54Z")

</div>

> but it is limited

I’m not sure what you mean by “limited”. In what way is it limited, what would you rather have it “include”?

I’m curious, what do you need this for? Is this for specifying the signature of some function? Seems dubious to include the type of one of the arguments as an argument itself (i.e. `10` is an `Int`, why include `Int` as an argument then?).

Maybe the following can be helpful / insightful:

```julia
julia> f(::Type{T}, x::T) where {T<:Signed} = 2x
f (generic function with 1 method)

julia> f(Int, 3)
6

julia> f(Int, 3.0)
ERROR: MethodError: no method matching f(::Type{Int64}, ::Float64)
Closest candidates are:
  f(::Type{T}, ::T) where T<:Signed at REPL[4]:1
Stacktrace:
 [1] top-level scope
   @ REPL[6]:1

julia> f(Float64, 3)
ERROR: MethodError: no method matching f(::Type{Float64}, ::Int64)
Closest candidates are:
  f(::Type{T}, ::T) where T<:Signed at REPL[4]:1
Stacktrace:
 [1] top-level scope
   @ REPL[7]:1

julia> f(Float64, 3.0)
ERROR: MethodError: no method matching f(::Type{Float64}, ::Float64)
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

```

---

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [September 16, 2022, 8:19am UTC](https://discourse.julialang.org/t/type-compare/87351/3 "2022-09-16T08:19:21Z")

</div>

`DataType` is too general, that would make the dispatch inconvinient.  
For example:

```julia
f(x::T) where T <: Tuple{Type{Int},Int}
    println(1)
end

f(x::T) where T <: Tuple{Type{Float64},Int}
   println(2)
end

```

While when using `DataType`, I can not do it.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [September 16, 2022, 8:25am UTC](https://discourse.julialang.org/t/type-compare/87351/4 "2022-09-16T08:25:57Z")

</div>

I might misunderstand what you mean, but the following would be the right way to make use of type dispatch to achieve what you want:

```julia
julia> f(x::Int) = println(1)
f (generic function with 1 method)

julia> f(x::Float64) = println(2)
f (generic function with 2 methods)

julia> f(1)
1

julia> f(1.0)
2

```

---

<div class="post-metadata">

**Author:** ![Brian1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brian1/32/49250_2.png) [@Brian1](https://discourse.julialang.org/u/Brian1)\
**Post date:** [September 16, 2022, 8:34am UTC](https://discourse.julialang.org/t/type-compare/87351/5 "2022-09-16T08:34:30Z")

</div>

The situation I met is a little more complicated. To copy all codes here may be unrelizable, but in simple words, I am finding a way to define `T <: Tuple{some_custom_struct_name, some_instance_of_other_struct}`

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [September 16, 2022, 8:45am UTC](https://discourse.julialang.org/t/type-compare/87351/6 "2022-09-16T08:45:38Z")

</div>

Without any context, `DataType` would work:

```julia
julia> struct A
       x
       end

julia> struct B
       x
       end

julia> typeof((A, B(1)))
Tuple{DataType, B}

julia> (A, B(1)) isa Tuple{DataType, B}
true

```

But I have no idea what this would serve or how exactly this is too “limited” (I think you mean the opposite, permissive).

It does sound a lot like a question about multiple dispatching. Try to extract a MWE from your full case. Take your time to read [Please read: make it easier to help you](https://discourse.julialang.org/t/please-read-make-it-easier-to-help-you/14757) and I’m sure we’d be able to help you.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [September 16, 2022, 2:40pm UTC](https://discourse.julialang.org/t/type-compare/87351/7 "2022-09-16T14:40:32Z")

</div>

I think people have tried hard enough to find the XY problem here. The author insists that this is useful to them. I am also stumped by this behavior:

```julia
julia> Int isa Type{Int}
true

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

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

```

Why is the last line false?

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [September 16, 2022, 6:03pm UTC](https://discourse.julialang.org/t/type-compare/87351/8 "2022-09-16T18:03:27Z")

</div>

`typeof(Int)` is `DataType`, and its supertype hierarchy goes:

```julia
julia> typeof(Int) |> supertypes
(DataType, Type{T}, Any)

```

And even though `Int isa Type{Int}`, checking whether `typeof(Int) <: Type{Int}` returns `false`. I don’t really understand the relationship between `DataType` and `Type{Int}`, especially in the context of putting it to use here.

Jeff Bezanson in a [2018 comment](https://github.com/JuliaLang/julia/issues/29368#issue-363791025) says:

> types like `DataType` and `Type{Int}` have an overly-complex subtype and specificity relationship: one is not a subtype of the other, but their intersection is non-empty, and we’re not able to accurately represent that intersection. For various reasons (including backwards compatibility) subtyping currently gets this wrong on purpose, making `Type{Int} <: DataType` true.

which at least assures me that it really is (known to be) a complex relationship. I also read through the Julia Manual’s Types page to figure out this relationship, but it doesn’t go into much detail about it either.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [September 16, 2022, 6:25pm UTC](https://discourse.julialang.org/t/type-compare/87351/9 "2022-09-16T18:25:46Z")

</div>

The impression I get from issues like [#11535](https://github.com/JuliaLang/julia/issues/11535), [#10947](https://github.com/JuliaLang/julia/issues/10947), [#29368](https://github.com/JuliaLang/julia/issues/29368) , and [this one](https://github.com/simonbyrne/KeywordDispatch.jl/issues/10) is that it’s not possible to dispatch on tuples containings types as elements, with the kind of specificity OP asks for. (The first two are closed issues from Julia 0.4/0.5 days, but the latter two issues refer to the same problem, and it seems like the first two were closed in a WONTFIX sense rather than as SOLVED, and the behaviour carried over into Julia 1.x versions too.)

Taking a hint from the suggestion in #11535, we can work around this using a helper method, where the tuple members are passed in as individual arguments rather than in a tuple.

```julia
julia> f(t::Tuple{DataType, Int}) = f(t[1], t[2])
f (generic function with 1 method)

julia> f(x::Type{Int}, y::Int) = @show(x, y)
f (generic function with 2 methods)

julia> f((Int, 10));
x = Int64
y = 10

julia> f((Float64, 10))
ERROR: MethodError: no method matching f(::Type{Float64}, ::Int64)
Closest candidates are:
  f(::Type{Int64}, ::Int64) at REPL[92]:1
...

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [September 16, 2022, 7:54pm UTC](https://discourse.julialang.org/t/type-compare/87351/10 "2022-09-16T19:54:18Z")

</div>

> [@digital\_carver](#):
>
> And even though `Int isa Type{Int}`, checking whether `typeof(Int) <: Type{Int}` returns `false`. I don’t really understand the relationship between `DataType` and `Type{Int}`, especially in the context of putting it to use here.

Other way around. This is the one example of an abstract type subtyping (and being more specific than) a concrete type I can think of.

```julia
julia> Type{Int} <: typeof(Int) # DataType
true
julia> Tuple{Type{Int}} <: Tuple{DataType}
true

```

As you quoted, it’s weird and doesn’t fit the wider subtyping rules, but this “hack” allows dispatch on specific types (as long as they’re not packaged in tuples). It would be more consistent with the rules if types were more like functions i.e. `typeof(T)` is a concrete parametric or singleton type that subtypes an abstract `Type`, but Julia v0 / v1 didn’t turn out that way.

> [@digital\_carver](#):
>
> Taking a hint from the suggestion in #11535, we can work around this using a helper method, where the tuple members are passed in as individual arguments rather than in a tuple.

The confusing part for me is I had always assumed that dispatch _was_ done on a [tuple of the function and the arguments](https://docs.julialang.org/en/v1/devdocs/functions/#Function-calls), e.g. `f(Int, 1.0)` dispatches on `Tuple{typeof(f), DataType, Float64}`. And that’s perfectly capable of being dispatched to a method `function f(T::Type{Int}, x::AbstractFloat)`. So there should be some explanation of how the dispatch to `Type{Int}` is really handled and why it doesn’t work when there’s an extra level of nested Tuple e.g. `f( (Int, 1.0) )` dispatching on `Tuple{typeof(f),Tuple{DataType,Float64}}`.
