Implement a function for Vectors of all subtypes

question

#1

I have a problem i can’t find a solution for.
Lets say I have a abstract supertype

abstract A

and a subtype

type B <: A
  value::Vector
end

(others might want to have value e.g. to be a matrix or something)

And I implemented a few functions for each subtype, maybe f1(p::B)::Float64 (and for other subtypes, too…) and now I’d like to implement a function such as

function myVFun(p::Vector{A},lambda::Integer)
  sum( [ f1(v) for v in p] )
  # but really this is of course more complicated involving 2-3 functions all available for each subtype of A
  return ...
end

Somehow the method dispatch does not call this function if I now have a Vector{B} (because this is not a subtype of Vector{A}?). But however I qould like to be able to implement (and call) such a function using vectors of subtypes. Because all functions I apply to the elements of p::Vector{A} are available for B <: A

How can I do that?


#2

Vector{B} is not a sub-type of vector{A}

from the docs:

Even though Float64 <: Real we DO NOT have Point{Float64} <: Point{Real}.
In other words, in the parlance of type theory, Julia’s type parameters are invariant, rather than being covariant (or even contravariant).

what you are looking for is something along these lines:

function myVFun{T <: A}(p::Vector{T},lambda::Integer)
  return sum( [ f1(v) for v in p] )
end

Basically you are defining a parametric function for every type that is a sub-type of A


#3

And I can call the function then with myVFun(f), when f::Vector{B}?


#4

Use a parameterized type this way:

import Base: length

abstract A{T}
type B{T} <: A{T}
   value::Vector{T}
end

length{T}(x::B{T}) = length(x.value)

function myFunction{T}(x::B{T})
    n = length(x)
    s = "A vector of type Vector{$T} and length $n."
    return s
end

myInts = B( [1,2,3] )
myChars = B( ['a', 'b', 'c', 'd'] )

myFunction(myInts)
myFunction(myChars)

Running that displays

julia> myInts = B( [1,2,3] )
B{Int64}([1,2,3])

julia> myChars = B( ['a', 'b', 'c'] )
B{Char}(['a','b','c'])

julia> myFunction(myInts)
"A vector of type Vector{Int64} and length 3."

julia> myFunction(myChars)
"A vector of type Vector{Char} and length 4."

Do you questions about how this example works?

You can have specialized handling for vectors of a given type:

# specialize the handling of Bs with Integer vectors
function myFunction{ T<:Integer }(x::B{T})
    s = "Specialized Handling for Bs with Integer vectors"
    return s
end

now running the example displays

julia> myFunction(myChars)
"A vector of type Vector{Char} and length 3."

julia> myFunction(myInts)
"Specialized Handling for Bs with Integer vectors"

#5

Thanks @jsarnoff your example made the point very clear and even the specialization is neatly explained. The method dispatching now works.

Edit: And it even works for operator overloading in order to use the subtype constructor

+{B <: A}(a::T,b::T) = T(a.value+b.value)

thats really neat!