1

如何在 Scala 中声明实现多个算术系统所需的类型签名,这些算术系统都共享相同的特征来声明操作?我以为我已经解决了,直到我尝试向基本特征/类添加一些辅助实现。在以下代码片段(可编译)中,请注意 sq() 被定义为 this*self 而不是更明显的 this*this。而且 self() 也不能在 trait 中实现(我们必须等到我们得到一个具体的扩展类来实现它)。

trait NumberBase [NUMBERTYPE <: NumberBase[NUMBERTYPE]] {
   // type NUMBERTYPE >: this.type
   def *(that: NUMBERTYPE):NUMBERTYPE
   def self:NUMBERTYPE
   def sq:NUMBERTYPE = { this*self }
}

class D(val v:Double) extends NumberBase[D] {
   def self:D = { this }
   def *(that: D):D = { new D(this.v*that.v) }
}

问题/目标是:删除 self() 的使用或(至少将 self() 的实现移动到 NumberBase 中)而不更改 D 中 * 的类型签名。上述链接中的许多修复使派生类无法实现(像 new D() 这样的东西不是由 * 或 * 返回的类型,在 D 中具有不可猜测的类型签名)。我不介意一些签名变得更丑 - 但我希望代码表达这段代码所表达的内容:派生类仅在它们自己的类型上工作并返回它们自己类型的实例(它们不会上下移动在层次结构中)。

我在这里找到了一些讨论,列出了一些问题(但没有看到解决方案):http ://www.scala-lang.org/node/839 。在看到基类和实现之前,您不会遇到一些问题。

此处给出了具有上述解决方法的完整代码(强制实现类实现 self()):https ://github.com/WinVector/AutoDiff在这里我们使用不同的算术系统共享相同的基类或特征这一事实编写在不同算术实现上通用的函数。这让我们可以使用标准机器算术(如 D)或其他东西(如计算梯度作为副作用的数字系统)的包装。

4

1 回答 1

3

我认为您想使用自类型,这将确保NumberBase[N]实例将是 type 的实例N

trait NumberBase[N <: NumberBase[N]] { this: N =>
  def *(that: N): N
  def sq: N = this * this
}

class D(val v: Double) extends NumberBase[D] {
  def *(that: D): D = new D(this.v * that.v)
}

val a = new D(0.5)
val b = new D(0.25)

a * b  // D(0.125)
a.sq   // D(0.25)

但是,如果你真的想定义一种新的数字类型,你应该做 Scala 库本身所做的事情并使用Numeric类型类。

于 2012-09-23T21:53:45.667 回答