Scala-用于不同输入类的相同方法

时间:2018-07-11 20:26:00

标签: scala

想象一下以下课程

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中重复代码的正确方法是什么?

1 个答案:

答案 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)
}

一种完全不同的方法将更多地基于面向对象,并且具有AlgebraicVector都可以继承的类似Matrix的特征。但是,当它们来自其他库时,这会更加困难,因此您最终不得不将它们包装在自己的类中。然后,您遇到了F界多态性带来的并发症...我只需要选择typeclass。