Scala,无法避免循环参数化

Scala,无法避免循环参数化,scala,types,Scala,Types,我已将我的问题简化为MWE(最小(非)工作示例)。下面是: 首先,我们有一个数据类型Loss,它本质上是一个函数2,因此在T中是逆变的 abstract class Loss[-T] { def apply(actual: T, predicted: T): Double } 接下来,我们有一个标签,其中损失是属性: abstract class Labeled[+T <: Labeled[T]] { def loss[Q >: T]: Loss[Q] } 不管我

我已将我的问题简化为MWE(最小(非)工作示例)。下面是:

首先,我们有一个数据类型
Loss
,它本质上是一个
函数2
,因此在T中是逆变的

abstract class Loss[-T] {
    def apply(actual: T, predicted: T): Double
}
接下来,我们有一个标签,其中损失是属性:

abstract class Labeled[+T <: Labeled[T]] {
    def loss[Q >: T]: Loss[Q]
}
不管我如何尝试参数化它,我得到了一个循环定义。如何做到这一点,或者如果没有,请告诉我我的想法是错误的


我是如何开始工作的(警告:糟糕的黑客):我已经从标签为
中删除了
丢失
的抽象规范,并在所有子类中保留了上述定义。当我需要对标记为
的常规类调用
loss
时,我会对每个可能的子类进行模式匹配。我希望有一天能解决这个问题。

正如评论中所说的那样,您不能用值覆盖参数化方法,因此您可能必须将
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] 
因此,现在您可以使用它:

 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)

有一个矛盾。您试图用值
loss
覆盖方法
loss
。但方法可以有类型参数(每次调用时都调整实际类型),而值不能-它有静态定义的类型在scala中,您可以用值重写方法,对吗?我想要实现的是能够将[Q>:T]的任意损失传递给标记的[T]或其case类。这不是一个参数化的方法。我想要构造一个case类,它以任意损失[Q>:T]扩展标记的[T]。那怎么做呢?例如:Numerical('test,x:Loss[NumericalSuperclass])不清楚您为什么说标签为
自然是协变的。您想要什么用例?谢谢。我会尽力让它工作的。您是否有任何可能涵盖高级scala类型系统功能的好资源?
 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)