Concrete typeof

Is there a function to get the concrete (numeric) type of some object of abstract type without much information about it? Consider these two bad methods:

using LinearAlgebra
x = [[1,2],[3,4]]
typeof(dot(x,x))
eltype(eltype(x))

The first method requires me to compute the dot product. The second requires knowledge of how many levels of abstract types I must go through before reaching the concrete-type bedrock. To give some context, this is for an optimization package.

Edit: I thought for a second and recursion solves this very easily I think:

function eleltype(x)
    elt = eltype(x)
    elelt = eltype(eltype(x))
    elt == elelt ? elt : eleltype(elelt)
end

So I see two options. You could store your vectors into a matrix and eltype() will retrieve the correct type:

using LinearAlgebra
x = [[1,2],[3,4]]
y = [1 2; 3 4]

dot(x,x) == dot(y,y) #true
eltype(y) # Int64

Or the other option is to use recursion:

deep_eltype(x) =  eltype(x) <: Number ? eltype(x) : deep_eltype(first(x))

y = [[[[1]]]]
deep_eltype(y) #Int64

There is LinearAlgebra.promote_leaf_eltypes:

julia> using LinearAlgebra

julia> x = [[1,2],[3,4]]
2-element Vector{Vector{Int64}}:
 [1, 2]
 [3, 4]

julia> LinearAlgebra.promote_leaf_eltypes(x)
Int64
1 Like

Thanks a lot Robert. Since the goal is to accept any input from users, the second one is better. To make it work for empty arrays, I would suggest this slight modification:

deep_eltype(x) =  eltype(x) <: Number ? eltype(x) : deep_eltype(eltype(x))
1 Like

Thanks a lot. I thought this might already exist but I couldn’t find it. In the help for eltype, it says “See also: keytype, typeof.” Suggesting promote_leaf_eltypes would be useful, although it does appear to be specific to LinearAlgebra.

not sure if this is public API tbh

1 Like