Array{T, 1} where T<:Real versus Array{T where T<:Real, 1}

T1 = Array{T, 1} where T<:Real represents all possible arrays of the form [T, T, T, T, . . . ], i.e., any array of T1 consists of elements of the subtype of Real and they have to be of same type.

On the other hand, T2 = Array{T where T<:Real, 1} represents all possible arrays of the form [T, T', T'', T''', ...]. So any array of T2 consists of elements of subtypes of Real but they could be of different types to each other.

Therefore I feel it is obvious that T2 can represent broader range of values than T1 can do. And if then, T1 <: T2 should hold but actually the evaluation of T1 <: T2 returns false.

Julia 1.2.0 manual explains that T2 is concrete type and T1 is abstract type, the fact of which can also be checked by trying T1() and T2() and maybe used as another justification of T2 <: T1. But I really don’t understand why T1 is abstract while T2 is concrete.

Could any one help me clear my confusion?

Thanks!

Hello,

If I’m not wrong, the link https://docs.julialang.org/en/v1/manual/types/index.html should help answer your query. To quote from the link, "even though Float64 <: Real we do not have Point{Float64} <: Point{Real}. For example,

julia> Float64 <: Real
true

julia> Array{Float64} <: Array{Real}
false
2 Likes

@bashonubuntu, thanks for replying! :slight_smile:

I see. So it looks like the answer to the question is closely related to type invariance. But specifically how the type invariance applies to this particular case (like math proof) is not crispy clear. Perhaps, I suppose full understanding requires learning type theory.

for the case of Float64 <: Real, Array{Float64} and Array{Real} are unrelated in the sense that Array{Float64} <: Array{Real} does not hold, nor does Array{Real} <: Array{Float64}. T1 and T2 above are related however: T2 <: T1.

In your example, T <: Real but Point{T} <: Point{Real} is false. In your example, Point is basically Array which seems consistent with the link I shared above.

julia> T1 = Array{T} where T<:Real
Array{T,N} where N where T<:Real

julia> T2 = Array{T where T<:Real}
Array{Real,N} where N

julia> T1<:T2
false

1 Like

Think about types in terms of sets, see docs here.

Vector{Int}, Vector{Float64}, Vector{Real} are all members of the set of T1, but only Vector{Real} is a member of the set of T2. Thus T1 is not a subset of T2, but T2 is a subset of T1.

3 Likes

Thanks @Mattriks, viewing in therms of sets is indeed much better approach! Let me ruminate for some more time for full digestion. :slight_smile: Perhaps I will be bringing some more queries on this later on…