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}` .