Help understanding type error: Int64 and Number

I would appreciate if someone could help me understand this. I know that in Julia you don’t have to specify types of function arguments. But if possible, I want to do it because it helps me understand the code more easily.

I defined a function with one of the arguments being a dictionary of type
Dict{Tuple{Number, Number}, Number}. When I explicitly create an instance of this argument (using numerical values) Julia assigns that value the type Dict{Tuple{Int64, Int64}, Float64}. When I pass this value to the function I get the following error (please see argument number 3). Since both Int64 and Float64 are subtypes of Number, I thought this should work. Where am I going wrong?
Interestingly, no such error is thrown for the first two arguments.

ERROR: MethodError: no method matching exp_payoff(::Tuple{Int64,Int64}, ::Int64, ::Dict{Tuple{Int64,Int64},Float64}, ::Int64, ::Int64, ::Set{Tuple{Int64,Int64}}, ::Distributions.Poisson{Float64}, ::Distributions.Poisson{Float64}, ::Distributions.Poisson{Float64}, ::Distributions.Poisson{Float64}, ::Float64)
Closest candidates are:
  exp_payoff(::Tuple{Number,Number}, ::Number, ::Dict{Tuple{Number,Number},Number}, ::Number, ::Number, ::Any, ::Distributions.Poisson, ::Distributions.Poisson, ::Distributions.Poisson, ::Distributions.Poisson, ::Any)

See Types · The Julia Language, especially the note

even though Float64 <: Real we DO NOT have Point{Float64} <: Point{Real} .


Thank you @kristoffer.carlsson. That link was helpful.

To complement, we have:

Point{Float64} <: Point{<:Real}

I am writing to help and also to make things more clear to me:

When one writes Vector{Float64} we are referencing a vector that can only contain Float64 numbers. A vector of type Vector{Real} can contain any type of real number. While a Vector{Real} can by chance contain only Float64 numbers, it will never have the constraint of only having one type of numbers. At the same time, of course, a Vector{Float64} will never be able to contain other type of number than Float64. Thus, one type of vector is not a subtype of the other, they are different things.

Horrible analogies here: In chess, the Queen can move as the Tower, but that does not make the Tower a subtype of Queen. A men’s toilet is not a unisex toilet that happens to have only men inside.

These rationale applies to concrete types (that is, types that actual vectors will assume). Thus, we have:

julia> x = Real[ 1, 2.0 ];

julia> y = Float64[ 1.0, 2.0 ];

julia> typeof(y) <: typeof(x)

julia> typeof(x) <: typeof(y)

When one uses <: we are obtaining abstract types. That is why Vector{Float64} <: Vector{<:Real} or even Vector{Real} <: Vector{<:Real} are both true. We are here asking if the concrete types Vector{Float64} and Vector{Real} are subtypes of an abstract type of vector that may or not be able to contain any type of Real number in them. These are the comparisons we happen to have in mind when doing this kind of confusion:

  1. Is a vector that can only contain Float64 numbers a subtype of the abstract type of vectors that may or not be able to contain any kind of Real number in them? is translated to Vector{Float64}<:Vector{<:Real}.

  2. Is a vector that can only contain Float64 numbers a subtype of the type of vectors than are able to accept other types of Real numbers? is translated to Vector{Float64}<:Vector{Real}, and is false because Vector{Real} does not have the constraint that the first type has.

1 Like