I was actually arguing in the other direction – if leading type parameters
match, narrow those in the typejoin. That would make
typejoin(Woo{Int,Int},Woo{Int,Float64}) == Woo{Int}. You could also do that
for non-leading type parameters but that seems less obvious somehow. That
would mean that typejoin(Woo{Int,Int},Woo{Float64,Int}) == Woo{*,Int} where
we don't currently have an input syntax for that last type (but we can
create it using a type alias).On Wed, Apr 1, 2015 at 2:16 PM, Jeff Bezanson <[email protected]> wrote: > Yes, arguably typejoin should just walk up the hierarchy and not try > to do fancier joins. However if there are no parameters in common, > e.g. > > a = Wow{W, X}() > b = Wow{Y, Z}() > > then the result would be Any. > > On Wed, Apr 1, 2015 at 11:45 AM, Stefan Karpinski <[email protected]> > wrote: > > Arguably typejoin should do that. > > > > On Wed, Apr 1, 2015 at 11:35 AM, Michael Francis <[email protected]> > > wrote: > >> > >> In this instance I'm happy to have the abstract type as the promoted > type. > >> E.g. I would like to see this be Array{Foo{Int64},1} and not > Array{Foo{K},1} > >> Can I satisfy this with a promote rule ? > >> > >> On Wednesday, April 1, 2015 at 11:29:08 AM UTC-4, Stefan Karpinski > wrote: > >>> > >>> 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): > >>> > >>> 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} > >>> > >>> > > >
