我已将问题减少到MWE(最小(非)工作示例)。在这里:
首先,我们有一个数据类型Loss
,它基本上是Function2
,因此在T中是逆变的。
abstract class Loss[-T] {
def apply(actual: T, predicted: T): Double
}
接下来,我们有一个Labeled,其中包括遗失:
abstract class Labeled[+T <: Labeled[T]] {
def loss[Q >: T]: Loss[Q]
}
它也是自然协变的,它必须是F-有界的。到目前为止,程序编译。当我想要创建Labeled
抽象类的具体案例类实现时,问题就出现了。我试过这个:
Error:(9, 12) class Numerical needs to be abstract, since method loss in class Labeled of type [Q >: Numerical]=> Loss[Q] is not defined
case class Numerical(name: Symbol, loss: Loss[_ >: Numerical]) extends Labeled[Numerical] {
^
但是我试着对它进行参数化,我得到了一个循环定义。怎么可能这样做,或者如果没有,告诉我我在想什么。
我如何开始工作(警告:糟糕的黑客):我已从loss
中删除了Labeled
的抽象规范,并将上述定义保留在所有子类中。当我需要在一般loss
类上调用Labeled
时,我会为每个可能的子类进行模式匹配。我希望有一天能够解决这个问题。
答案 0 :(得分:3)
正如评论中所述,您无法使用值覆盖参数化方法,因此您可能需要将Q
移出loss
的定义:
abstract class Labeled[+T <: Labeled[T]] {
type TT <: T
type Q >: TT
def loss: Loss[Q]
}
case class Numerical(name: Symbol, loss: Loss[Numerical#Q]) extends Labeled[Numerical]
您可能想要指定Q本身(存在类型_ >: Numerical
,此处用Q >: TT
表示,否则将解析为Any
):
case class Numerical(name: Symbol, loss: Loss[Numerical#Q]) extends Labeled[Numerical] {
type Q = Numerical //can only be >: than Numerical
}
现在你可以使用它了:
scala> :paste
// Entering paste mode (ctrl-D to finish)
Numerical('a, new Loss[Numerical#Q] {
def apply(actual: Numerical#Q, predicted: Numerical#Q): Double = {
actual.loss //check that it's available, as you put `Q = Numeric`
0L
}
})
// Exiting paste mode, now interpreting.
res19: Numerical = Numerical('a,$anon$1@6355264c)