The language does have both Wow{Int64,_} – which can be expressed easily as
Wow{Int64} – and Wow{_,Int64} – which has no easy syntax but still exists
(you can create a syntax for it with typealias). I'm not entirely clear on
what the inconsistency here is, although it would be nice to have a concise
definition of what precisely typejoin computes. The help entry for
typejoin(T, S) is "Compute a type that contains both T and S", which, while
correct, is a bit vague – it could just return Any all the time by that
definition.On Wed, Apr 1, 2015 at 4:10 PM, Michael Francis <[email protected]> wrote: > To clarify I'm looking for the paramaterized types behave consistently > with non paramaterised types. That is not the case at the moment. > > abstract x > type a <: x end > type b <: x end > type c <: x end > typeof( [ a(),b(),c() ]) # Array{x,1} > > If I have paramaterized types with no common super class then Any would > seem to be a reasonable answer given the current state of the language. > If the language is extended to support Wow{ Int64,_ } and Wow{ _, Int64 } > etc then I can see the argument to collapse to common types. > > > On Wednesday, April 1, 2015 at 3:55:42 PM UTC-4, Jeff Bezanson wrote: >> >> 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} >> >>> >>> >> >>> >>> >> >>> > >> >> >> >> >> > >> >
