Dispatch rules for Union types

257 views
Skip to first unread message

Simon Byrne

unread,
May 29, 2014, 2:43:14 PM5/29/14
to juli...@googlegroups.com
I'm trying to understand the dispatch rules for Union types. Suppose that I define a Transpose wrapper type, and I want a specific behaviour for a Matrix or its Transpose:

immutable Transpose{T, S <: AbstractMatrix{T}} <: AbstractMatrix{T}
    data::S
end

typealias NormTrans{T,S} Union(S,Transpose{T,S})

foo(a::AbstractMatrix) = 1
foo{T}(a::NormTrans{T,Matrix}) = 2

However when I run it I get:

julia> foo(ones(2,2))

1

Yet according to @which this shouldn't happen:

julia> @which foo(ones(2,2))

foo{T}(a::Union(Array{T,2},Transpose{T,Array{T,2}})) at none:1

I've also found that I can kind-of cheat by switch the parameter order in the alias:

typealias NormTrans{S,T} Union(S,Transpose{T,S})
foo(a::AbstractMatrix) = 1
foo(a::NormTrans{Matrix}) = 2

This now works for Matrix types, but not Transposes:

julia> foo(ones(2,2))

2

julia> foo(Transpose{Float64,Matrix{Float64}}(ones(2,2)))

1

(and yes, I know I could get around this by defining foo(::Matrix) and foo(::Transpose) methods, but this can cause a combinatorial explosion when there are multiple arguments)

Jeff Bezanson

unread,
May 29, 2014, 2:54:56 PM5/29/14
to juli...@googlegroups.com
`foo{T}(a::NormTrans{T,Matrix})` is not applicable for the call
`foo(ones(2,2))` because it is not possible to determine the value of
`T`. The `Matrix` part of `NormTrans` matches, but this doesn't
specify `T`. This is a subtlety that which doesn't seem to take into
account (yet).

Simon Byrne

unread,
Oct 17, 2014, 4:20:13 AM10/17/14
to juli...@googlegroups.com
To follow up, one possible solution is to use macros instead of a typealias:

immutable Transpose{T, S <: AbstractMatrix{T}} <: AbstractMatrix{T}
    data::S
end

macro NormTrans(M)
    M.head == :curly || error("Argument of @NormTrans must be a parametric type.")
    T = M.args[2]
    :(Union($M,Transpose{$T,$M}))
end

foo(a::AbstractMatrix) = 1
foo{T}(a::@NormTrans(Matrix{T}) = 2
Reply all
Reply to author
Forward
0 new messages