I am trying to define a method in scala that takes a generic type of S[_] <: Seq[Double]
and returns a S[FixedLoad] (FixedLoad is a concrete type). But my implementation gives me errors and I can't figure out why. Despite I have tried so many times to understand parametric types and higher-kinded types, my knowledge grows so slow.
What I am trying to achieve is to not lose the concrete type of S (the sequence subtype).
Here is the code:
import scala.collection.generic.CanBuildFrom
class FixedLoad(val id: Int, val positionInT: Int, val amplitude: Double) {
override def toString: String = s"FixedLoad($id, $positionInT, $amplitude)"
}
object Load {
implicit def toFixedLoads[S[_] <: Seq[Double]](l: S[Double])(implicit cbf: CanBuildFrom[Nothing, FixedLoad, S[FixedLoad]]): S[FixedLoad] = {
l.map(_ => new FixedLoad(1, 1, 1)).to[S]
}
def main(args: Array[String]): Unit = {
println(toFixedLoads(List(1.0, 2.0, 3.0)))
}
}
and the errors:
Error:(16, 13) inferred type arguments [List] do not conform to method toFixedLoads's type parameter bounds [S[_] <: Seq[Double]]
println(toFixedLoads(List(1.0, 2.0, 3.0)))
Error:(16, 30) type mismatch;
found : List[Double]
required: S[Double]
println(toFixedLoads(List(1.0, 2.0, 3.0)))
S[Double] <: Seq[Double]
.Double
doesn't refer to the standard library class when you do that. Rather,Double
is a local type variable. The boundS[Double] <: Seq[Double]
, in this context, means "for all typesDouble
, thenS[Double] <: Seq[Double]
". Write something clearer, likeS[X] <: Seq[X]
. You can observe this meaning inclass X[+A]; def m[S[Double] <: X[Double]](s: S[Int]): X[Int] = s
. To convertS[Int]
toX[Int]
, the quantified bound is instantiated withDouble = Int
to getS[Int] <: X[Int]
. – Nyaya