想象一下以下课程
class A{
def update(x: Vector, y: Vector): Vector = {
x + 0.5 * y
}
def update(x: Matrix, y: Matrix): Matrix = {
x + 0.5 * y
}
}
两种方法之间的唯一区别是输入类型。统一这些方法并避免在Scala中重复代码的正确方法是什么?
答案 0 :(得分:4)
我建议为常见的代数运算定义一个类型类:
trait Algebra[A] {
def plus(x: A, y: A): A
def timesScalar(x: A, d: Double): A
}
implicit val vectorAlgebra = new Algebra[Vector] {
def plus(x: Vector, y: Vector): Vector = x + y
}
// ... same for Matrix ...
def update[A](x: A, y: A)(implicit alg: Algebra[A]): A = {
alg.plus(x, alg.timesScalar(y, 0.5))
}
如果您想轻松地为类型类生成一些语法糖,也可以研究simulacrum,以便在理论上可以做得更简单一些:
def update[A : Algebra](x: A, y: A): A = {
x + (y * 0.5)
}
一种完全不同的方法将更多地基于面向对象,并且具有Algebraic
和Vector
都可以继承的类似Matrix
的特征。但是,当它们来自其他库时,这会更加困难,因此您最终不得不将它们包装在自己的类中。然后,您遇到了F界多态性带来的并发症...我只需要选择typeclass。