# 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! 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. Perhaps I will be bringing some more queries on this later on…