Type of Array of NamedTuples with same names but different tuples

I want to write a function that iterates over arrays of named tuples. In particular, I want to write a map reduce that pulls the names up to the highest level:

function sel_map_red(nt::AbstractArray{NamedTuple{names, T}, N}; m=identity, r=identity)  where {names, T, N}
    NamedTuple{names}(map(names) do n
        r(map(el->m(el[n]), nt))
    end)
end

This works fine for arrays where all the names have identical types:

b=[(a=1,), (a=2,)]
sel_map_red(b)

However it breaks if the elements of the array have the same names, but different types:

b = [(a=1,), (a=true,)]
sel_map_red(b)

I believe it has something to with Tuples not being covariant? Broader (non-concrete) types in NamedTuple

The first line evaluates to true, but the second line doesnt

typeof(b) <: Array{NamedTuple{names,T} where T<:Tuple,1} where {names}
typeof(b) <: Array{NamedTuple{names,T},1} where {names, T}

I can change the signature of sel_map_red to be the first line, but then it will work in the second example and not the first.

What Iā€™m at a loss to do is to write a single type signature for sel_map_red that accepts both:

b=[(a=1,), (a=2,)]
b=[(a=1,), (a=true,)]

You could drop all the type annotations and extract the names like this:

function sel_map_red(nt; m=identity, r=identity)
    names = fieldnames(typeof(first(nt)))
    NamedTuple{names}(map(names) do n
        r(map(el->m(el[n]), nt))
    end)
end
1 Like