Correct argument type for ::Array{Array{<:Real,1},1})

I would like to understand why

``````function foo(A::Array{Array{<:Real,1},1}) end
``````

does not accept

``````foo(fill(Float64[],10))
``````

I know that

``````function foo(A::Array{Array{T,1},1}) where T <: Real end
``````

works but I need to understand why. I thought I understood julia parametric types but apparently not.

1 Like

This is because

``````julia> Array{Array{<:Real,1},1} == Array{Array{T,1} where T<:Real,1}
true
``````

but what you really want is, as you noted: `Array{Array{T,1}} where {T<:Real,1}`.

1 Like

you mean `<:Real` right ?

Yes, sorry. I guess I answered a bit too hastily. I’ll edit my post to fix this.

The point was that it’s merely an issue with syntax and where the “`where`” clause is introduced when using the shortened notation `A{B{<:C}}`. This experience should not lead you to question your understanding of invariance and such topics.

1 Like

`Array{Array{<:Real,1},1}` is an array of arrays, where each sub-array might have a different element type. But I think that’s likely to be kind of confusing, so let’s simplify with some helpful names. I think you’ll agree that your initial argument type could be written as:

``````julia> A = Array{<:Real, 1}
Array{#s2,1} where #s2<:Real

julia> B = Array{A, 1}
Array{Array{#s2,1} where #s2<:Real,1}
``````

The type of `fill(Float64[], 10)` is:

``````julia> typeof(fill(Float64[], 10))
Array{Array{Float64,1},1}
``````

So we can rewrite that as:

``````julia> C = Array{Float64, 1}
Array{Float64,1}

julia> D = Array{C, 1}
Array{Array{Float64,1},1}
``````

An array of floats is a subtype of `Array{<:Real}`:

``````julia> C <: A
true
``````

But that doesn’t mean that `Array{C, 1} <: Array{A, 1}` :

``````julia> Array{C, 1} <: Array{A, 1}
false
``````

for exactly the same reason that:

``````julia> Array{Float64, 1} <: Array{Real, 1}
false
``````
5 Likes

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

``````Warning

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

Your issue is just a special case of the above warning as @rdeits elucidated so clearly above.

Okay, thank you I got it. Actually it made sense as soon as you said that each Array could have a different element type. Sweet.