No, you’re not doing anything wrong. These types are determined by inference, and inference is an imperfect approximation. There’s no limit to how hard inference could try to get types as exact as possible — and indeed it will never be able to figure out some cases (see: Halting problem - Wikipedia). So at some point it must give up and return an approximation. The only question is where to draw that line.
In my experience, once inference can no longer concretely figure out one of the parameters (N in this case), it doesn’t “try” as hard to figure out the other parameters. If, instead, you make sure that all the inner arrays are two-dimensional, it’s able to determine the types exactly.
well tuples are not really attractive as they are sometimes difficult to deal with. say I want to sum two of them I cannot simply write a+b. Is it that wrong to use Array{Array} with different sizes? Thank you!
The T in Vector{T} represents a TypeVar wildcard — it can indeed match any type. It might be a Vector{Any}, but it could also be a Vector{Int} or Vector{Real}. This may get more obvious in the future as there are changes planned to how this prints. It might eventually be printed as Vector{T} where T <: Any.
This is different from Any in Vector{Any} — here Julia actually knows more about the type. It knows that it will definitely be a heterogenous array that can contain any object.
This is particularly significant because Julia’s type parameters are invariant.