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}
>> >>> >>>
>> >>> >>>
>> >>> >
>> >>
>> >>
>> >
>>
>

Reply via email to