我正在尝试编写一个Value Class来为实现Seq[_]
的任何东西添加功能,并允许它进行返回Future[_]
的批量调用(具体来说,我用它来进行批量REST调用) )。
final class BatchedList[A, C[X] <: Seq[X]](val targetList: C[A]) extends AnyVal {
def batchRequests[B](batchSize: Int)(runner: Seq[A] => Seq[Future[Either[Result, B]]])
(implicit bf: CanBuildFrom[C[A], Either[Result, B], C[Either[Result, B]]]): Future[Either[Result, C[B]]] = {
targetList.grouped(batchSize).foldLeft(Future.successful(bf(targetList))) { (results, set) =>
results flatMap { responses =>
Future.sequence(runner(set)).map(responses ++=)
}
} map {
_.result().sequenceU
}
}
}
但是,我无法编译。我一直收到编译错误
value sequenceU is not a member of type parameter C[Either[play.api.mvc.Result,B]]
我已导入scalaz._
和Scalaz._
,我知道他们为我的用例Traverse[_]
提供了List[_]
这个例子)。我很确定这是类型的某种隐式解决问题,但我很难理解如何继续解决它。
答案 0 :(得分:1)
我认为这是因为Scalaz不为Seq
提供类型类实例,而是为IndexedSeq
和List
提供类型实例。因此,您需要自己提供Traverse
实例(请注意C
的其他隐式参数batchRequests
):
final class BatchedList[A, C[X] <: Seq[X]](val targetList: C[A]) extends AnyVal {
def batchRequests[B](batchSize: Int)(runner: Seq[A] => Seq[Future[Either[Result, B]]])
(implicit bf: CanBuildFrom[C[A], Either[Result, B], C[Either[Result, B]]], C: Traverse[C]): Future[Either[Result, C[B]]] =
targetList.grouped(batchSize).foldLeft(Future.successful(bf(targetList))) { (results, set) =>
results flatMap { responses =>
Future.sequence(runner(set)).map(responses ++=)
}
} map {
_.result().sequenceU
}
}
如您所见,这将返回与C
提供的类型对应的序列类型:
scala> def run[A](s: Seq[A]): Seq[Future[Either[Result, A]]] =
| s.map(i => Future.successful(Right(i)))
run: [A](s: Seq[A])Seq[scala.concurrent.Future[Either[Result,A]]]
scala> :t new BatchedList(List(1,2,3)).batchRequests(1)(run)
scala.concurrent.Future[Either[Result,List[Int]]]
scala> :t new BatchedList(Vector(1,2,3)).batchRequests(1)(run)
scala.concurrent.Future[Either[Result,scala.collection.immutable.Vector[Int]]]
如果你总是希望它返回一个Seq
,这只是一个简单的问题。