Concrete types for Dicts in container

Hi everyone!

I am trying to construct a container that holds vectors of different probabilities (but they are all either multi- or univariate). This container is used to store prior distributions of parameter I use in another struct, so one of the fields is a Dict that maps symbols to Vectors of distributions. The following could be used for a concrete type definition:

using Distributions
using BenchmarkTools

#3 - Issue for concrete types
typeof( [Normal(), Normal() ] ) #Vector{Normal{Float64}}
typeof( [Gamma(1,2), Normal() ] ) #Vector{Distribution{Univariate, Continuous}}
typeof( [Normal(), Normal() ] ) <: Vector{<:Distribution{Univariate} } #true
typeof( [Gamma(1,2), Normal() ] ) <: Vector{<:Distribution{Univariate} } #true
typeof( [Poisson(1), Normal() ] ) <: Vector{<:Distribution{Univariate} } #true

#all combinations above are subtype of Vector{<:Distribution{Univariate} }
Dict(:μ => [Normal(1,2), Normal(3,4)],
     :δ => [Gamma(1,1), Exponential(1)] ) #Dict Symbol -> Array{T,1} where T
#but somehow here no concrete type is assigned

So as a first guess I would assign the following container:

struct Prior01{A<:VariateForm}
    α       ::  Dict{Symbol, Vector{<:Distribution{A}} }
end
# Concretely typed not working
p01 = Prior01( Dict(:μ => [Normal(1,2), Gamma(3,4)],
             :δ => [Gamma(1,1), Gamma(1,1)] )  )

For some reasons I do not understand, this is not working - so a non-concretely typed version so far is the best I could do:

struct Prior02
    α       ::  Dict{Symbol, <:Vector{C} where {C} }
end

#Working but no concrete type
p02 = Prior02( Dict(:μ => [Gamma(1,2), Gamma(3,4)],
             :δ => [Gamma(1,1), Gamma(1,1)] )  )

Question: Does anyone know why I cannot get the concretely typed container working even though the Vectors of Distributions shown above have a common supertype?

Best regards,

Does eltype() return the same for [Gamma(1,2), Gamma(3,4)] and [Gamma(1,1), Gamma(1,1)]? If not, then their closest common supertype is indeed Vector{<:Any}.
If you want to have Vector{Distribution} as the value type for the dictionary, then use it explicitly when calling the constructor:

p02 = Prior02( Dict{Symbol, Vector{Distribution}}(:μ => [Normal(1,2), Gamma(3,4)],
             :δ => [Gamma(1,1), Gamma(1,1)] )  )

Note, however, that Vector{Distribution} isn’t a concrete type, so you still get boxing there. But that still provides a hint to the type inference system.

2 Likes

I don’t think this matters in practice. For the compiler, it is commonly just best to bail to Any for non-concrete types.

1 Like

Thank you for your answer! eltype()does return the same for
[Gamma(1,2), Gamma(3,4)] and [Gamma(1,1), Gamma(1,1)], but not for
[Normal(1,2), Gamma(3,4)] and [Gamma(1,1), Gamma(1,1)],
which I think you might have meant?

In that case, I will have to resort to Anythen, as you two suggested.