Reputation: 45
I'm currently working on a project that includes Gaussian Processes for Machine Learning. Considering the examples and explanations in the book, I'm trying to create a generic function for the various parameters that are part of a trained GP-object - thus, the following declaration is the most general one for a (simple) training function.
def train[T, M <: MatrixInverter[T], S <: Kernel[T]](): GP_Spawn[T] = null
(I've removed the parameter list and the implementation, just if you're wondering.)
T
describes the numeric type, e.g. it may be Double
or Int
. MatrixInverter[T]
is a trait that enforces a calculateInverse
function. Kernel[T]
is the corresponding trait for a kernel-function.
As some of you may already know, training in a gaussian process can be changed (somehow simplified) when using a Cholesky-Decomposition as the matrix-inverter - thus, I've considered to specialize the function mentioned above. Due to the documentation of the @specialized
tag, it should be something like this:
def train[T, @specialized(CholeskyDecomposition[T]) M <: MatrixInverter[T], S <: Kernel[T]](): GP_Spawn[T]
It's obvious that all parameters are more or less depending on T
, since they need to use some variables (types T
,Vector[T]
,Matrix[T]
) that depend on it. If I try to compile the code mentioned above, the scala-compiler (2.9.2) complains about
error: not found: value CholeskyDecomposition
I'm not sure what this means, since the import import algorithms.{CholeskyDecomposition, MatrixInverter}
is correct. Besides, it's curious to see that the import of CholeskyDecomposition
is marked as Unused import statement. CholeskyDecomposition
has a companion that includes some constants that are related to the algorithm itself, but I don't assume this aspect to be the reason for this error.
Any ideas what may cause this error ? And, furthermore, how to solve it without cutting of the generic approach ?
Edit:
After reading the answers are considering some re-ordering of my code, I ended up with a solution at runtime that uses type-matching.
val testMat = new Matrix[T](3, 3)
val testInv = fac(testMat)
testInv match {
case chol : CholeskyDecomposition[T] => println("Found Cholesky!")
case _ => println("Found something different.")
}
And it works now :) Thanks to all!
Upvotes: 2
Views: 196
Reputation: 167891
If you have a class C
that is specialized on type T
, then
class D[@specialized T, C[T]](c: C[T]) { ... }
will use the T
-specialized verson of C
.
This is all you need anyway. There is no point to specialization on object; generic code works just as well since everything non-primitive is an object anyway.
Upvotes: 3
Reputation: 40461
You can only specialize a generic parameter with a primitive type: Int
, Double
, etc. So you can specialize T
but not Foo[T]
even if T
is a primitive.
Upvotes: 5