This is computed by the promote_type and typejoin functions defined in promotion.jl:
https://github.com/JuliaLang/julia/blob/master/base/promotion.jl promote_type tries to find a single concrete type to convert a collection of types to. As a fallback, if it can't do that, it calls typejoin on the types, which walks up the type hierarchy and tries to find a common abstract supertype of its arguments. Since these types don't have any promote_rule methods, all examples fall back on typejoin, which exhibits the behavior you're seeing here: julia> typejoin(typeof(a)) Wow{Int64,Int64} julia> typejoin(typeof(a),typeof(b)) Wow{K,V} julia> typejoin(typeof(a),typeof(c)) Foo{Int64} julia> typejoin(typeof(a),typeof(b),typeof(c)) Foo{Int64} julia> typejoin(typeof(a),typeof(c),typeof(b)) Foo{Int64} julia> typejoin(typeof(a),typeof(b),typeof(c),typeof(d)) Foo{K} One way to hook into this system and get different results is to define promote_rule methods to determine what "wins" when you promote different Wow and Foo types together. For example, you could define this (requires a restart dues to #265 <https://github.com/JuliaLang/julia/issues/265>): Base.convert{K,V}(::Type{Wow{K,V}}, x::Wow) = Wow{K,V}() Base.promote_rule{K1,V1,K2,V2}(::Type{Wow{K1,V1}}, ::Type{Wow{K2,V2}}) = Wow{promote_type(K1,K2),promote_type(V1,V2)} After that [a, b] constructs an Array{Wow{Int64,Float64},1} instead of an Array{Wow,1}. The conversion method is a bit odd here since Wow doesn't have any fields, but you would do the appropriate conversions if there were fields. If there's some appropriate way to pick a common type between Wow and Foo objects, that can also have promote_rules. On Wed, Apr 1, 2015 at 11:02 AM, Michael Francis <[email protected]> wrote: > If I run the following, I get the results show to the right (in comments), > it appears array construction fails to raise to the common > parent type under certain conditions, is there a way round > this? Alternatively where is this code implemented ? > > abstract Foo{K} > type Wow{K,V} <: Foo{K} end > type Bar{K,V} <: Foo{K} end > > a = Wow{Int64, Int64}() > b = Wow{Int64, Float64}() > c = Bar{Int64, Int64}() > d = Bar{Int64, String}() > > println( "******" ) > println( typeof( [ a ])) #Array{Wow{Int64,Int64},1} > println( typeof( [ a, b ])) #Array{Wow{K,V},1} > println( typeof( [ a, c ])) #Array{Foo{Int64},1} > println( typeof( [ a, b, c ])) #Array{Foo{Int64},1} > println( typeof( [ a, c, b ])) #Array{Foo{Int64},1} > println( typeof( [ a, b, c, d ])) #Array{Foo{K},1} >
