I think in this case we want a union-free join. Otherwise the type
could be as big as the result value.

I also think many people would find it surprising if

typejoin(Wow{X,X}, Wow{Y,Y}) = Wow

but

typejoin(Wow{Int,String}, Wow{Int, Float64}) = Foo{Int}

That rule basically gives higher priority to the parameters, when I
would expect the type name to have higher priority. The best thing
would be to keep the join minimal and use Stefan's suggestion of
Wow{Int,_}.

On Wed, Apr 1, 2015 at 3:47 PM, Michael Francis <[email protected]> wrote:
> @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]> 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}
>>> >>>
>>> >>>
>>> >
>>
>>
>

Reply via email to