如何在Scala中声明类型参数化算术



如何在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) }
}

问题/目标是:在不更改D中*的类型签名的情况下,删除self()或(至少将self(的实现移动到NumberBase中)的使用。上面链接中的许多修复使派生类无法实现(比如new D()不是可由*返回的类型,或者*在D中具有不可访问的类型签名)。我不介意一些签名变得更丑陋,但我希望代码能表达这段代码所表达的内容:派生类只处理自己的类型,并返回自己类型的实例(它们不会在层次结构中上下移动)。

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

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

我认为您想要使用self-type,这将确保NumberBase[N]实例也将为类型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类型类。

最新更新