Promote_type of nested tuple elements


I have nested tuples like

tup = Tuple{Tuple{Int64,Int8},Tuple{Int128,Int32}}

and I need to find the largest eltype of the elements, i.e. Int128 in the above case. I feel I need to use promote_type in a recursive fashion, but my attempts have failed so far.



What are your attempts so far?


I think I got it. Here it is

using Base.Test

promote_tuple_type(a::Number) = typeof(a)
promote_tuple_type(a::Tuple) = promote_type(map(promote_tuple_type, a)...)

# basic tests
tup0 = ((1, 1), (1, 2), (2, 3), (2, 3, 4), ((2, 3, (3, 4, (5, 5, (1,))))))
tup1 = ((Int8(1), Int32(1)), (Int64(1), Float64(1)))
tup2 = ((Int8(1), Int32(1)), (Int64(1), Int128(1)))
tup3 = (((Int8(1), Int32(1)), (Int64(1), Int128(1))), (Float32(1), Float16(1)))

@test promote_tuple_type(tup0) == Int64
@test promote_tuple_type(tup1) == Float64
@test promote_tuple_type(tup2) == Int128
@test promote_tuple_type(tup3) == Float32

This works well, but maybe there is better way of doing it.


The related problem is to construct a new tuple where all elements have the same type. I came up with two options

convert_tuple{T}(::Type{T}, a::Number) = T(a)
convert_tuple{T}(::Type{T}, a::Tuple) = (map(el->convert_tuple(T, el), a)...)
convert_tuple{T}(::Type{T}, a::Tuple) = (convert_tuple.(T, a)...)

The second looks nicer but incurs in more allocations than the first.

These works OK for me, but again, there might be a better way of doing it.