What is the correct way to use the type alias Vector and Matrix in multiple dispatch?

636 views
Skip to first unread message

Po Choi

unread,
Apr 6, 2016, 4:23:16 PM4/6/16
to julia-users

hello(A::Matrix) = 1
hello(A::Vector{Matrix}) = 2
A = randn(3,3);
AA = [randn(3,3) for k in 1:4];
hello(A)
hello(AA)

The output has method error.
julia> hello(A)
1

julia> hello(AA)
ERROR: MethodError: `hello` has no method matching hello(::Array{Array{Float64,2},1})


If I write down the types explicitly,
hi(A::Array{Float64,2}) = 1
hi(A::Array{Array{Float64,2},1}) = 2
A = randn(3,3);
AA = [randn(3,3) for k in 1:4];
hi(A)
hi(AA)
The output is what I expect.
julia> hi(A)
1

julia> hi(AA)
2

Am I using Vector and Matrix in a wrong way?

Yichao Yu

unread,
Apr 6, 2016, 4:44:38 PM4/6/16
to Julia Users
On Wed, Apr 6, 2016 at 4:23 PM, Po Choi <vegeta...@gmail.com> wrote:
>
> hello(A::Matrix) = 1
> hello(A::Vector{Matrix}) = 2

http://julia.readthedocs.org/en/latest/manual/types/#parametric-composite-types

Vector{Matrix{Float64}} is not a subtype of Vector{Matrix}

Sisyphuss

unread,
Apr 6, 2016, 6:38:55 PM4/6/16
to julia-users
You may want to apply `@vectorize_1arg` macro to `hello`.

Po Choi

unread,
Apr 6, 2016, 7:58:50 PM4/6/16
to julia-users

Does it make sense to declare a variable with the type `Matrix`?

julia> methods(hello)
# 2 methods for generic function "hello":
hello(A::Array{T,2}) at none:1
hello(A::Array{Array{T,2},1}) at none:1

julia
> AA = [randn(3,3) for k in 1:4];

julia
> AAA = Matrix[randn(3,3) for k in 1:4];


julia> hello(AA)
ERROR: MethodError: `hello` has no method matching hello(::Array{Array{Float64,2},1})

julia> hello(AAA)
2


julia> typeof(AA)
Array{Array{Float64,2},1}

julia> typeof(AAA)
Array{Array{T,2},1}

julia> Array{T,2}
ERROR: UndefVarError: T not defined


I am a little bit confused about the `T`. Why can `T` appear inside `AAA` without being declared?

Andy Ferris

unread,
Apr 6, 2016, 9:24:34 PM4/6/16
to julia-users
T is meant to be a parametric type, defined in this case in the definition of Matrix (as a type alias) and also Array (as a type parameter with the same name). In typeof(AAA) it's pulling T out of that definition of the typealias. You could have written AAA = Matrix{Float64}[randn(3,3) for k in 1:4] to define T.

Further, types in Julia are not covariant which means even if A <: B, we do NOT have Type{A} <: Type{B}. In your case that reads Matrix{Float64} <: Matrix, but not Vector{Matrix{Float64}} <: Vector{Matrix}.

To be generic, your function definitions could take a type parameter, like:

    hello{T}(A::Vector{Matrix{T}}) = 2

Here we have introduced a new "parameteric type" variable "T". It could have been named anything. It works since there is some T (==Float64) where it will find a match. 

Or, to be specific about the input type, just define:

    hello(A::Vector{Matrix{Float64}}) = 2

You don't have to be afraid of using Matrix and Vector, but you do have to think about how that might interact with the non-covariant type system. In cases like these AFAIK the only way to make a generic function is to introduce type parameters (using either Array{T,2} or Matrix{T} should be fully equivalent).

Does that help?
Andy

Po Choi

unread,
Apr 8, 2016, 2:30:03 AM4/8/16
to julia-users
Thanks.

One point I don't understand is the type alias `Matrix{T}` with parametric type `T`.

julia> foo{T}(A::Vector{Matrix{T}}) = 1

foo (generic function with 1 method)


julia> methods(foo)

# 1 method for generic function "foo":

foo{T}(A::Array{Array{T,2},1}) at none:1


julia> bar(A::Vector{Matrix}) = 1

bar (generic function with 1 method)


julia> methods(bar)

# 1 method for generic function "bar":

bar(A::Array{Array{T,2},1}) at none:1


julia> baz(A::Vector{Matrix{T}}) = 1

ERROR: UndefVarError: T not defined



I can define `foo{T}(A::Array{Array{T,2},1})`.
I can define `bar(A::Array{Array{T,2},1})`  by using type alias `Matrix` without `{T}`
But, I cannot define `baz` as above without `{T}`.
Is it fair?

Eric Forgy

unread,
Apr 8, 2016, 4:10:36 AM4/8/16
to julia-users
julia> foo{T}(A::Vector{Matrix{T}}) = 1

This says: foo is a function with parameter "T" that takes an argument of type "Vector{Matrix{T}}".

No problem.

julia> bar(A::Vector{Matrix}) = 1


This says: bar is a function with no parameters that takes an argument of type "Vector{Matrix}". 

However, "Vector" is a typealias for "Array{T,1}" for some type "T". So whether or not you explicitly state the parameter, "Vector" is still a parameterized typed. 

No problem.

baz(A::Vector{Matrix{T}}) = 1

This says: baz is a function with no parameter that takes an argument "Vector{Matrix}" with parameter "T".

See the problem? 

To use a parameter, you need to specify that the function has a parameter.

This section of the documentation might be helpful: TypeVars.

Hope this helps.

Best regards,
Eric
Reply all
Reply to author
Forward
0 new messages