@Jeff - I'd expect this behavior - e.g. I'd get Any or Wow{K,V} if there
were no common super type. The other option would be to generate a union(
Wow(W,X), Wow{Y,Y} ) in those cases ... not sure of the penalty of that
though. In the example I gave I'd expect Foo{Int64} as this is a common
super type.
On Wednesday, April 1, 2015 at 2:55:21 PM UTC-4, Stefan Karpinski wrote:
>
> 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]
> <javascript:>> 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]
>> <javascript:>> wrote:
>> > Arguably typejoin should do that.
>> >
>> > On Wed, Apr 1, 2015 at 11:35 AM, Michael Francis <[email protected]
>> <javascript:>>
>> > 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}
>> >>>
>> >>>
>> >
>>
>
>