2014-10-28 3 views
0

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 
     } 
    } 
    } 

그러나 컴파일 할 수 없습니다. 나는 모두 scalaz._Scalaz._을 가져온 컴파일러 오류

value sequenceU is not a member of type parameter C[Either[play.api.mvc.Result,B]] 

를 받고 계속하고, 나는 그들이 (이 예에서는 List[_]입니다) 내 사용 사례에 대한 Traverse[_]을 제공 한 것을 알고있다. 저는 이것이 타입에 대한 암묵적인 해상도 문제 일 것이라고 확신 합니다만, 앞으로 해결할 방법에 대해 잘 모르겠습니다.

답변

1

Scalaz는 Seq에 대한 typeclass 인스턴스를 제공하지 않고 대신 IndexedSeqList을 제공하기 때문에 이러한 현상이 발생한다고 생각합니다. 당신이 볼 수 있듯이

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로 제공 유형에 해당하는 시퀀스 유형을 반환합니다 따라서, 당신은 Traverse 예를 자신 (추가 암시 인수 CbatchRequests에주의)를 제공해야합니다 :

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을 반환합니다.

+0

'_.result()'의 결과는'Seq [_]'이 아니고'C [_]'인데리스트에서 호출 할 때'List [_]'이어야합니다 – Jeff

+0

언제 'List'를 호출했을 때, 실제로'Future [Result, List [B]]] - 당신이 요구 한 것이 아닌가? 나는 이것을 설명하기 위해 나의 대답을 편집했다. – Hugh

+0

알았어, 나는 암시적인 C : Traverse [C]의 추가를 놓쳤다. 그럼 내 질문에, 왜 추가 매개 변수가 필요한 것 같아? 함수 선언과 동일한 범위에서'Scalaz._'를 가진 모든 함축을 가져 왔으므로 왜 그것을 메서드 시그니처에 추가해야합니까? 암묵적인 해결 규칙에 대해 혼란스러워합니다. – Jeff