First of all, note that this is a problem specific to Array : your method works for List or any other regular collection (except for those that have several type parameters or not). Example:
scala> parN(List(1,2,3), 2) res17: scala.collection.parallel.ParIterable[Int] = ParVector(1, 2, 3) scala> parN(Set(1,2,3), 2) res18: scala.collection.parallel.ParIterable[Int] = ParSet(1, 2, 3)
Array always a special case when it comes to collections, because ... it's not a collection. Because of Java, its definition is final class Array[T] extends Serializable with Cloneable . However, there are two options available everywhere that can convert Array to collection type ( ArrayOps and WrappedArray ). And these types implement Parallelizable , so everything should be fine ... except that type inference is in the way:
The type parameter is only defined as T[S] , so when it receives Array[Int] it gladly displays Array[Int] , and then checks the boundaries: failure, Array not distributed Parallelizable . Game over.
I see two options:
You can explicitly say you want Parallelizable :
def parN[S](collection: Parallelizable[S, ParIterable[S]], n: Int)
Or, if you need access to the actual type T (in your case not, but who knows):
def parN[S, T[S] <: Parallelizable[S, ParIterable[S]]](collection: T[S] with Parallelizable[S, ParIterable[S]], n: Int)
or you can accept anything that can be implicitly converted to Parallelizable using an implicit parameter:
def parN[S, T <% Parallelizable[S, ParIterable[S]]](collection: T, n: Int)
which is a short version:
def parN[S, T](collection: T, n: Int)(implicit ev: T => Parallelizable[S, ParIterable[S]])
All of them should work. In your case, I would recommend the very first: this is the most readable one that does the job.
gourlaysama
source share