Type checking in Dictionaries

The Julia style guide says,

For example, don’t declare an argument to be of type Int or Int32 if it really could be any integer, expressed with the abstract type Integer
(https://docs.julialang.org/en/v1/base/numbers/#Core.Integer)

However, this creates some issues when dealing with Dictionaries. As an example:

x = Dict(1=>[1,2,3])
display(x isa Dict{Integer,Vector{Integer}})
display(x isa Dict{Int64,Vector{Int64}})

The first option (using Integer) returns false. The second option (using Int) returns true. Any thoughts here?

This is just that Julia’s types are invariant. You want Dict{<:Integer, Vector{<:Integer}}.

4 Likes

Adding the <: continues to return false

julia> x = Dict(1=>[1,2,3])
Dict{Int64,Array{Int64,1}} with 1 entry:
  1 => [1, 2, 3]

julia> x isa Dict{<:Integer, <:Vector{<:Integer}}
true

Here Vector{<:Integer} isa UnionAll type

julia> Vector{<:Integer}
Array{#s3,1} where #s3<:Integer

and Vector{Int} is a concrete type from the union.

1 Like

Ok. Adding the additional <: before Vector works. I guess for Dictionaries its just easier to disregard the Julia style guide and use Int instead of Integer with all those <:.

Thanks for the help.

Yes you should absolutely use concrete parametric types while creating objects, eg Dicts. The suggestion for abstract types is usually for function arguments

3 Likes

No, the style guide is correct, what you are missing is the concept of invariance, see

https://docs.julialang.org/en/v1/manual/types/#Parametric-Abstract-Types-1

The solution given by @jishnub is the correct way to dispatch on subtypes of a parametric type without narrowing down to a concrete one.

1 Like

Good point. I see that there is a clear warning on this in the documentation right above the section on parametric abstract types. Thanks!

Concrete Point types with different values of T are never subtypes of each other:

julia> Point{Float64} <: Point{Int64}
false

julia> Point{Float64} <: Point{Real}
false

Warning

This last point is very important: even though Float64 <: Real we DO NOT have Point{Float64} <: Point{Real} .