Samik R
Samik R

Reputation: 1638

Scala: method value doesn't conform to type bounds

I am trying to write a code which saves a typed variable value. Here is the sample code:

class MethodTypeTest
{
    trait TSM[T <: TSM[T]]
    {
        def fit(): FiM[T]
    }

    trait FiM[T <: TSM[_]]
    {
        val fitErrors = mutable.HashMap[String, Double]()
    }

    class TS
    {
        //*** Here I am saving the value of the variable after some computation.
        var bestModel: Option[FiM[_]] = None
    }

    // Now define for SMA
    class SMAM extends FiM[SMA]
    {
        fitErrors("RMSE") = 10
    }
    class SMA extends TSM[SMA]
    {
        override def fit() = new SMAM()
    }
    // Now define for DMA
    class DMAM extends FiM[DMA]
    {
        fitErrors("RMSE") = 10.5
    }
    class DMA extends TSM[DMA]
    {
        override def fit() = new DMAM()
    }

    def main(args: Array[String]): Unit =
    {
        val ts = new TS
        val sma = new SMA
        val dma = new DMA
        val fms: Array[FiM[_]] = Array[FiM[_]](sma.fit(), dma.fit())
        val bestModel: FiM[_] = fms.minBy(m => m.fitErrors("RMSE"))
        // ******** Error in below line ******
        // Error:(48, 24) type arguments [_$3] do not conform to trait FiM's type parameter bounds [T <: MethodTypeTest.this.TSM[_]]
        //        ts.bestModel = Some(bestModel)
        ts.bestModel = Some(bestModel)
    }
}

Looks like the compiler is complaining that the type bound is too open in the last line. I have intentionally kept the type of bestModel open in the statement var bestModel: Option[FiM[_]] = None, while defining class TS, since this value will be computed later to one of the FiM's. How/where can I specify the type bound so that this works?

Upvotes: 0

Views: 55

Answers (1)

Dan Simon
Dan Simon

Reputation: 13137

I was able to get this to compile (with scastie using Scala 2.13.4) by adding in type bounds _ <: TSM[_] everywhere you have a FiM[_] type annotation:

class TS {
    var bestModel: Option[FiM[_ <: TSM[_]]] = None
}
//...

val fms: Array[FiM[_ <: TSM[_]]] = Array(sma.fit(), dma.fit())
val bestModel: FiM[_ <: TSM[_]] = fms.minBy(m => m.fitErrors("RMSE"))

I believe this is needed because otherwise it thinks that the unknown TSM[_] type parameter of the array must match that of the val, so specifying that it too should be wildcard avoids that.

Upvotes: 2

Related Questions