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


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}

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))

So we can rewrite that as:

julia> C = Array{Float64, 1}

julia> D = Array{C, 1}

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

julia> C <: A

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

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

for exactly the same reason that:

julia> Array{Float64, 1} <: Array{Real, 1}

Directly from we see


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.