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