I’m new to Julia and I’m trying to understand how type deduction works for generic functions with parametric types. To test my hands at things, I tried to define a function that takes one argument that should be a vector-like of tuples with two elements, a numeric matrix-like and a string. So I tried the following:

f(::AbstractVector{Tuple{AbstractMatrix{T},String}}) where T<:Number = @show T

I then defined a matrix a

a = [ 11 12 13 ; 21 22 23 ]

and expected f( [(a, "a")] ) to be equivalent to @show Int64, but instead got the error:

Hi there! If we take things step by step to check subtyping, we’ll see what went wrong:

julia> a isa AbstractMatrix
true
julia> (a, "a") isa Tuple{AbstractMatrix, String}
true
julia> [(a, "a")] isa AbstractArray{Tuple{AbstractMatrix, String}}
false
julia> [(a, "a")] isa AbstractArray{<:Tuple{AbstractMatrix, String}}
true

The problem here is that just because two types satisfy T1 <: T2 doesn’t mean AbstractArray{T1} <: AbstractArray{T2}. The section of the docs explaining this is Parametric Composite Types.
Note that the behavior of Tuple is different from that of other parametric types, which is something I always struggle to remember.

I had already gone through the Types and More about types pages in the docs, but it’s a lot to digest, so I missed that particular aspect. The fact that when testing with tuples it hadn’t tripped didn’t help indeed

I’ve gone with AbstractVector{Tuple{M,String}} where M <: AbstractMatrix{<:Number}, but now I’ve got a related problem for “diagonal types”, if my understanding is correct. I’ll open a new topic for it. Thanks again.