我有this function将Array
转换为ParArray
,并将线程数作为参数:
def parN[T](collection: Array[T], n: Int) = {
val parCollection = collection.par
parCollection.tasksupport = new ForkJoinTaskSupport(
new concurrent.forkjoin.ForkJoinPool(n))
parCollection
}
现在我想使这个通用,以便它适用于Array
以外的集合:
def parN[S, T[S] <: Parallelizable[S, ParIterable[S]]](collection: T[S], n: Int) = {
val parCollection = collection.par
parCollection.tasksupport = new ForkJoinTaskSupport(
new concurrent.forkjoin.ForkJoinPool(n))
parCollection
}
但是when I call it与parN(Array(1, 2, 3), 2)
,我收到此错误:
inferred type arguments [Int,Array] do not
conform to method parN's type parameter bounds
[S,T[S] <: scala.collection.Parallelizable[S,scala.collection.parallel.ParIterable[S]]]
另一方面,这是有效的:
val x: Parallelizable[Int, ParIterable[Int]] = Array(1, 2, 3)
我的类型参数可能有什么问题?
答案 0 :(得分:5)
首先,请注意,这是Array
特有的问题:您的方法适用于List
或任何其他正常集合(除了具有多个类型参数的那些,或者没有)。示例:
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
在集合方面总是一个特例,因为......它不是一个集合。由于Java,它的定义是final class Array[T] extends Serializable with Cloneable
。但是,在任何地方都存在两个可以将Array
转换为集合类型(ArrayOps
和WrappedArray
)的含义。这些类型确实实现了Parallelizable
,所以一切都应该没问题......除了类型推断会妨碍:
您的类型参数仅定义为T[S]
,因此在收到Array[Int]
时,它会高兴地推断出Array[Int]
,然后检查边界:失败,Array
没有不会延长Parallelizable
。游戏结束。
我看到两个选项:
您可以明确表示您需要Parallelizable
:
def parN[S](collection: Parallelizable[S, ParIterable[S]], n: Int)
或者,如果您需要访问实际类型T
(在您的情况下没有,但谁知道):
def parN[S, T[S] <: Parallelizable[S, ParIterable[S]]](collection: T[S] with
Parallelizable[S, ParIterable[S]], n: Int)
或者您可以使用隐式参数接受任何可以隐式转换为Parallelizable
的内容:
def parN[S, T <% Parallelizable[S, ParIterable[S]]](collection: T, n: Int)
这是简短版本:
def parN[S, T](collection: T, n: Int)(implicit ev: T =>
Parallelizable[S, ParIterable[S]])
所有这些都应该有用。在你的情况下,我会推荐第一个:它是最可读的工作。