I want to write a function that can take matrix composing of both int and float and return if it is a upper triangle matrix or not:

function isUpperTriangle(A::Array{Number, 2}, tol::Number=1e-3)::Bool
for i in CartesianIndices(A)
if i[1] > i[2]
if A[i[1], i[2]] > tol
return false
end
end
end
true
end

function isUpperTriangle(A::Array{<:Number, 2}, tol::Number=1e-3)::Bool
for i in CartesianIndices(A)
if i[1] > i[2]
if A[i[1], i[2]] > tol
return false
end
end
end
true
end
julia> tt = [ 1 2 3; 0 3 4; 0 0 5];
julia> isUpperTriangle(tt)
true

The only difference is the Array{<:Number, 2} in the function signature instead of Array{Number, 2}.

By the way, it is often useful to write methods that are as general as possible (maybe not in this case, but thatâ€™s up to you). You could get the same functionality with this more general function:

function isUpperTriangle(A::AbstractMatrix, tol = 1e-3)
for i in CartesianIndices(A)
if i[1] > i[2]
if A[i] > tol
return false
end
end
end
true
end

Now this still works:

julia> isUpperTriangle(tt)
true

But now so does any matrix type, as long as tol was something comparable with the elements of A. Note below that tt' (tt transpose) is not an Array, but the function still works.

This is because Number is an abstract type and Float64 <: Number. Therefore a function written for x::Number can be compiled for Float64. However, Vector{Number} is a concrete type, and Vector{Float64} is therefore not a subtype of Vector{Number}. Since it is not a subtype, a function written for Vector{Number} cannot accept Vector{Float64}. This is why you must specify Vector{<:Number}.

By the way, this can be understood by realizing that it is possible to promote an array of Float64s to an array of Numbers, but it is never possible to promote a single Float64 to a Number. If a type can â€śexistâ€ť as an object, it is necessarily concrete.