# Subtyping Conventions for Dicts are Unexpected

If

``````Int64 <: Real
``````

is true, and I presume Julia follows normal function typing rules (for dicts) where the “return” type can be more specific than indicated by the type annotation, why isn’t the following true?

`````` Dict(:x=>[1,2], :y=>[1,2]) isa Dict{Symbol, Array{<:Real, 1}}
``````

Do I need to do something like:

``````Dict(:x=>[1,2], :y=>[1,2]) isa <:Dict{Symbol, Array{Real, 1}}
``````

Welcome!

In Julia, type parameters are invariant. So even though `Int <: Real` it is not true that `Array{Int} <: Array{Real}`.Your use-case is just another example of such type invariance.

``````julia> Int <: Real
true

julia> Array{Int} <: Array{Real}
false
``````

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

1 Like

What is happening here?

``````julia> [1,2] isa Array{<:Real,1}
true
``````

and here?

``````julia> Array{Int} <: Array{<:Real}
true
``````

Your last piece of code is equivalent to checking

``````julia> Array{Int} <: Array{T} where {T <: Real}
true
``````

The RHS is the set of all types of the form `Array{T} where {T<:Real}`. So, an element that belongs to `Array{Int}` is also an element of `Array{T} where {T<:Real}`. An element that belongs to `Array{Float64}` is also an element of `Array{T} where {T<:Real}` and so on

``````julia> Array{Float64} <: Array{T} where {T <: Real}
true
``````
1 Like

So it seems like I can get the kind of type variance behavior that I intuitively want to use – returning to the original question, why doesn’t this “hack” work for the more complex type? :

``````julia> Dict{Symbol, Array{Int,1}} <: Dict{Symbol, Array{<:Real, 1}}
false
``````

You need

``````julia> Dict{Symbol, Array{Int,1}} <: Dict{R, Array{T, 1}} where {R, T}
true
``````

Thanks!
I see that

``````julia> Dict{Symbol, Array{Int,1}} <: Dict{Symbol, Array{T, 1}} where {T <: Real}
true
``````

also works.

Is the way I am doing this not the “Julian” way to do things?

This is also fine and depends on whether you want to use a fixed type or its subset. What I wrote is slightly more generic because you can replace `R` with any subtype of `Symbol.` This is what you are doing with `Array{T, 1} where {T<:Real}` as well. You are allowing the code to compile for a subtype of `Real` so you have flexibility in that you can pass a subtype of `Real` in place of `T` like so

``````julia> Dict{Symbol, Array{Int,1}} <: Dict{Symbol, Array{T, 1}} where {T <: Real}
true

julia> Dict{Symbol, Array{Float64,1}} <: Dict{Symbol, Array{T, 1}} where {T <: Real}
true
``````

There is nothing non-Julian in what you did but I like to keep my code as generic as possible Notice that keeping the code like `Array{T, 1} where {T<:Real}` has no runtime penalty.

1 Like