Got it now, that's a good strategy.

Of course, it's the second one I'm more concerned about.

--Tim

On Friday, August 22, 2014 03:18:19 PM Jameson Nash wrote:
> For the first, you are missing the base case for the recursion, so it
> defaults to eltype(::Any) instead of eltype(::Type{MyAbstract{T}})
> 
> On Friday, August 22, 2014, Tim Holy <tim.h...@gmail.com> wrote:
> > On Friday, August 22, 2014 01:17:53 PM Jameson Nash wrote:
> > > Instead of eltype as written, use the following format:
> > > eltype{T<:...}(::Type{T}) = eltype(super(T))
> > 
> > With this definition:
> > Base.eltype{T<:MyAbstractType}(::Type{T}) = eltype(super(T))
> > 
> > eltype(MyType{Float32}) yields "Any".
> > 
> > 
> > And for the second:
> > julia> f{M<:MyAbstractType}(::Type{M}) = (M.name){Float32}
> > f (generic function with 1 method)
> > 
> > julia> f(MyType{Float64})
> > ERROR: type: instantiate_type: expected TypeConstructor, got TypeName
> > 
> >  in f at none:1
> > 
> > It was a good suggestion, it's just that I had already tried it.
> > 
> > --Tim
> > 
> > > This should help with the type inference issue too.
> > > 
> > > I think M.name is already the type, so you don't need to use eval (which
> > > doesn't return the right thing anyways, in the general case)
> > > 
> > > Sorry I can't type more clearly on a phone, but I'm hoping this will be
> > > enough to get you going in the right direction.
> > > 
> > > On Friday, August 22, 2014, Tim Holy <tim.h...@gmail.com <javascript:;>>
> > 
> > wrote:
> > > > Hi all,
> > > > 
> > > > I've come up against a couple of surprising type-manipulation issues
> > 
> > and
> > 
> > > > I'm
> > > > wondering if I'm just missing something. Hoping someone out there
> > 
> > knows a
> > 
> > > > better way of doing these manipulations.
> > > > 
> > > > The issues arise when I try writing generic algorithms on abstract
> > > > parametric
> > > > types that need to make decisions based on both the concrete
> > > > parameters
> > > > and
> > > > the concrete type. Let's start with a simple example:
> > > > 
> > > > abstract MyAbstractType{T}
> > > > 
> > > > immutable MyType{T} <: MyAbstractType{T}
> > > > 
> > > >     a::T
> > > >     b::T
> > > > 
> > > > end
> > > > 
> > > > Now let's write a generic "eltype" method:
> > > > 
> > > > Base.eltype{M<:MyAbstractType}(::Type{M}) = M.parameters[1]
> > > > 
> > > > It's a little ugly to have to use M.parameters[1] here. While I'm
> > 
> > curious
> > 
> > > > to
> > > > know whether I'm missing a simple alternative, I can live with this.
> > > > 
> > > > Now let's define some arithmetic operations:
> > > > 
> > > > (*)(x::Number, m::MyType) = MyType(x*m.a, x*m.b)
> > > > (.*)(x::Number, m::MyType) = MyType(x*m.a, x*m.b)
> > > > 
> > > > And then try it out:
> > > > julia> y = MyType(3,12)
> > > > 
> > > > julia> 2y
> > > > MyType{Int64}(6,24)
> > > > 
> > > > julia> 2.1y
> > > > MyType{Float64}(6.300000000000001,25.200000000000003)
> > > > 
> > > > 
> > > > So far, so good. Now let's try something a little more sophisticated:
> > > > 
> > > > julia> A = [MyType(3,12), MyType(4,7)]
> > > > 
> > > > 2-element Array{MyType{Int64},1}:
> > > >  MyType{Int64}(3,12)
> > > >  MyType{Int64}(4,7)
> > > > 
> > > > julia> 2A
> > > > 
> > > > 2-element Array{Any,1}:
> > > >  MyType{Int64}(6,24)
> > > >  MyType{Int64}(8,14)
> > > > 
> > > > The problem here is we're getting an Array{Any,1} back. No problem you
> > > > say,
> > > > let's try to help type inference out, by specifying that a
> > > > 
> > > > ::MyType{Int}*::Float64 is a MyType{Float64}. If we were willing to
> > 
> > write
> > 
> > > > this
> > > > using concrete types, it would be easy:
> > > > 
> > > > Base.promote_array_type{T<:Real, S}(::Type{T}, ::Type{MyType{S}}) =
> > > > MyType{promote_type(T, S)}
> > > > 
> > > > But if we want to just use the abstract type, then I've been
> > 
> > unsuccessful
> > 
> > > > in
> > > > avoiding this construction:
> > > > 
> > > > Base.promote_array_type{T<:Real, M<:MyAbstractType}(::Type{T},
> > ::
> > ::Type{M})
> > ::
> > > > =
> > > > eval(M.name.name){promote_type(eltype(M), T)}
> > > > 
> > > > Ouch! Do we really have to use eval there? This seems likely to be a
> > > > runtime
> > > > bottleneck, which seems confirmed by
> > > > 
> > > > code_llvm(Base.promote_array_type, (Type{Float64}, Type{eltype(A)}))
> > > > 
> > > > Compare it against the version generated when I instead use the
> > 
> > concrete
> > 
> > > > type,
> > > > and you'll see what I mean.
> > > > 
> > > > Of course these issues would be easily solved by triangular dispatch
> > > > or
> > > > staged
> > > > functions, but I'm hoping there's another good way that exists today.
> > > > 
> > > > --Tim

Reply via email to