Search code examples
scalageneric-programming

Scala generic upper bound


I'm trying to write a simple utility

def withParLevel[T, Col <: ParIterable[T]](coll: Col, ts: TaskSupport): Col = {
  coll.tasksupport = ts
  coll
} 
withParLevel(List(1,2,3,4,5).par, blockingPool)

Which gives me this error:

inferred type arguments [Nothing,scala.collection.parallel.immutable.ParSeq[Int]] do not conform to method withParLevel's type parameter bounds [T,Col <: scala.collection.parallel.ParIterable[T]]

How can I fix that?

Why does it infer T to Nothing, not to Int?

PS scala version 2.10.2


Solution

  • Change the type bound to View Bound. Scala compiler needs evidence between the two type parameters that Col => scala.collection.parallel.ParIterable[T]

    Let's have a quick REPL session: (For compilation I did not use the TaskSupport param)

    $ scala
    Welcome to Scala version 2.10.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> import scala.collection.parallel.ParIterable
    import scala.collection.parallel.ParIterable
    
    scala> def withParLevel[T, Col <: ParIterable[T]](coll: Col): Col = coll 
    withParLevel: [T, Col <: scala.collection.parallel.ParIterable[T]](coll: Col)Col
    

    Let's fix the compilation error using View Bounds:

    scala> def withParLevel[T, Col <% ParIterable[T]](coll: Col): Col = coll
    withParLevel: [T, Col](coll: Col)(implicit evidence$1: Col => scala.collection.parallel.ParIterable[T])Col
    
    scala> withParLevel(List(1,2,3,4,5).par)
    res0: scala.collection.parallel.immutable.ParSeq[Int] = ParVector(1, 2, 3, 4, 5)
    

    Edit: Reason: If one of the type bounds drives the other (in your case, Col derives the inference from T), you would need View Bounds.