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]))
}
在此代码中,我尝试将返回的类型Seq[Double]
转换为Seq[T]
。在执行呼叫时,T
可以是例如Double
或Int
。
归功于.asInstanceOf[T]
。
代码编译。
但如果我执行它,我会收到以下错误:
错误:(25,61)类型不匹配; 发现:( Seq [Double],Seq [Double])=> SEQ [T] 要求:( Seq [Any],Seq [Any])=> SEQ [任意] ).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]) )
错误:(25,13)类型不匹配; 发现:Seq [Any] 要求: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]) )
为什么执行失败?如何实现从Seq[Double]
到Seq[T]
的转换?
答案 0 :(得分:3)
首先,不,这段代码没有编译:那些是编译错误,而不是运行时异常。您可以看到,因为它以Error:
开头,指向源代码中的确切位置(例外只有行号),并且没有堆栈跟踪。
现在,如果它确实编译了,它就不会起作用,但这是一个单独的问题。
那为什么不编译呢? weights.zip(points).map(...)
的类型为Seq[Seq[Double]]
,因此reduce
的签名变为reduce[A1 >: Seq[Double]](op: (A1, A1) => A1): A1
。请注意,reduce
的参数的返回和参数类型必须匹配,在您的情况下,它们不会(您有(Seq[Double], Seq[Double]) => Seq[T]
)。本身就足够了,不能编译。
整个weights.zip(points).map(...).reduce(...)
的预期类型是Seq[T]
,因此编译器需要选择A1
:
超出Seq[Double]
的超类型以满足约束
Seq[T]
的子类型,使返回类型匹配
这样的类型不存在(没有T
的附加约束),但是如果它确实存在Seq[SomeType]
,那么就编译器应该得到的那样。为什么它最终显示Any
,我真的不明白。
如何实现从Seq [Double]到Seq [T]的转换?
如果你有weights: Seq[T], points: Seq[Seq[T]]
,那就更有意义了。在这种情况下,请使用Numeric
。 Stack Overflow上有很多答案,外面解释如何,例如,
对于weights: Seq[Double], points: Seq[Seq[Double]]
,我只想添加一个函数Double => T
作为额外参数:
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)
}
答案 1 :(得分:2)
我从Alexey那里得到了答案。 我会声明fromDouble是隐式的,并将转换器函数创建为隐式值,您可以按照自己的设计使用函数。 例如:
object DoubleConverters {
implicit val doubleToDouble: Double => Double = identity
implicit val doubleToInt: Double => Int = _.round.toInt
}
def linearInterpolation[T](weights: Seq[Double], points: Seq[Seq[Double]])(implicit converter: 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(converter)
// sample call
val result = linearInterpolation[Double]( weights = Seq(1.1, 1.3), Seq(Seq(1.1, 1.2), Seq(1.3, 1.4)))
//示例通话 val result = linearInterpolation [Double](权重= Seq(1.1,1.3),Seq(Seq(1.1,1.2),Seq(1.3,1.4)))
答案 2 :(得分:2)
因此类型类的效果相同:
trait DoubleConverter[T] {
def convert(d: Double): T
}
object DoubleConverter {
implicit val doubleToInt: DoubleConverter[Int] = new DoubleConverter[Int] {
override def convert(d: Double): Int = d.round.toInt
}
implicit val doubleToDouble: DoubleConverter[Double] = new DoubleConverter[Double] {
override def convert(d: Double): Double = d
}
}
def linearInterpolation[T](weights: Seq[Double], points: Seq[Seq[Double]])(implicit converter: DoubleConverter[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(converter.convert)
// sample call
val result = linearInterpolation[Int]( weights = Seq(1.1, 1.3), Seq(Seq(1.1, 1.2), Seq(1.3, 1.4)))
看到用法保持不变。我们避免意外的Double =>使用情况。