简体   繁体   中英

Scala generic type in trait

What I am trying to do :

trait BasicModel {
  type U <: BasicModel

  def -(that: U): BasicModel
  ...
}

class MatrixFactorizationModel(val W: DenseMatrix[Double], val b: Double) extends  BasicModel {
  type U = MatrixFactorizationModel

  def -(that: MatrixFactorizationModel): MatrixFactorizationModel =  new MatrixFactorizationModel(W + that.W, b - that.b)
  ...
}

abstract class SAG [T <: BasicModel#U : ClassTag] {
  //type T <: BasicModel#U    I also tried like that

  def modelDerivative(idx: Index, cstDerivative: Double): T

  def compute(): T = {
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))
  }
}

When compute is call I got this error :

type mismatch;
found   : T
required: _129.U where val _129: T
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))

I don't understand why this is not working because T is a BasicModel#U. Could someone explain me, and give me an alternative?


EDIT :

I also changed in SAG T <: BasicModel#u in T <: BasicModel and when I use T to change it in T#U :

abstract class SAG [T <: BasicModel : ClassTag] extends Optimizer {

  def modelDerivative(idx: Index, cstDerivative: Double): T#U

   ...
}

But :

type mismatch;
found   : T#U
required: _128.U where val _128: T#U
    SumDerivative = SumDerivative - modelDerivative(idx, Hist(idx))

It's sort of like the type defined in BasicModel, U, is a member of an instance of BasicModel. It's like the difference between static/instance variables in Java. To match a type definition, you need the exact same type. If it were static, you couldn't override it in the subclass, MatrixFactorizationModel.

T <: BasicModel in SAG represents any T <: BasicModel#U (the parent #U) where that #U could be any subtype of BasicModel. Even though you might happen to have specified MatrixFactorizationModel wherever you instantiated an instance of SAG, the compiler doesn't know what specific T you have in this context, or that it's a subtype of the same U.

You might have better luck with something like trait BasicModel { def [T<:BasicModel]-(that:T):T } . It's a bit more verbose, and can be a real pain if you've got a lot of method signatures to type, but sometimes signatures like that work out better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM