def linearInterpolation(weights: Seq[Double], points: Seq[Seq[Double]]) : Seq[T] = {
weights.zip(points).map(
weight_point => weight_point._2.map(coordinate => weight_point._1 * coordinate)
).reduce((point_a : Seq[Double], point_b : Seq[Double]) => point_a.zip(point_b).map(coordinate_points => (coordinate_points._1 + coordinate_points._2).asInstanceOf[T]))
}
In this code, I'm trying to convert the type of the return, a Seq[Double]
, to a Seq[T]
. At the execution of the call, T
could be e.g. Double
or Int
.
This conversion should be realized thanks to .asInstanceOf[T]
.
The code compiles.
But if I execute it, I get the following errors :
Error:(25, 61) type mismatch; found : (Seq[Double], Seq[Double]) => Seq[T] required: (Seq[Any], Seq[Any]) => Seq[Any] ).reduce((point_a : Seq[Double], point_b : Seq[Double]) => point_a.zip(point_b).map(coordinate_points => (coordinate_points._1 + coordinate_points._2).asInstanceOf[T]))
Error:(25, 13) type mismatch; found : Seq[Any] required: Seq[T] ).reduce((point_a : Seq[Double], point_b : Seq[Double]) => point_a.zip(point_b).map(coordinate_points => (coordinate_points._1 + coordinate_points._2).asInstanceOf[T]))
Why does the execution fail ? How to achieve this conversion from a Seq[Double]
to a Seq[T]
?
First, no, this code doesn't compile: those are compilation errors, not runtime exceptions. You can see because it starts with Error:
, points to an exact position in source code (exceptions only have a line number), and there's no stack trace.
Now, if it did compile, it wouldn't work, but that's a separate issue.
So why doesn't it compile? The type of weights.zip(points).map(...)
is Seq[Seq[Double]]
, so the signature of reduce
becomes reduce[A1 >: Seq[Double]](op: (A1, A1) => A1): A1
. Note that the return and argument types of reduce
's argument must match, and in your case they don't (you have (Seq[Double], Seq[Double]) => Seq[T]
). By itself that would be enough not to compile.
The expected type of the entire weights.zip(points).map(...).reduce(...)
is Seq[T]
, so the compiler needs to pick A1
which is:
a supertype of Seq[Double]
to satisfy the constraint
a subtype of Seq[T]
to make return types match
Such a type doesn't exist (without additional constraints on T
), but if it did it would be Seq[SomeType]
, and that's as far as the compiler should get. Why it ends up showing Any
, I really don't see.
How to achieve this conversion from a Seq[Double] to a Seq[T] ?
It makes more sense if you have weights: Seq[T], points: Seq[Seq[T]]
. In that case, use Numeric
. There's quite a few answers on Stack Overflow and outside explaining how, e.g. Scala equivalent of Java's Number.
For weights: Seq[Double], points: Seq[Seq[Double]]
, I would just add a function Double => T
as an extra argument:
def linearInterpolation(weights: Seq[Double], points: Seq[Seq[Double]])(fromDouble: Double => T) : Seq[T] = {
weights.zip(points).map(
weight_point => weight_point._2.map(coordinate => weight_point._1 * coordinate)
).reduce((point_a : Seq[Double], point_b : Seq[Double]) => point_a.zip(point_b).map(coordinate_points => coordinate_points._1 + coordinate_points._2)).map(fromDouble)
}