2014-08-29 3 views
2

"++"를 구현하는 일반 컨테이너를 사용하는 일반 함수를 작성하려고하지만 구문을 올바르게 알 수없는 것 같습니다.유형 경계가있는 일반 함수

def pagedRequest[A, C[_] <: Iterable](url: String, accumulator: C[A])(parser: (WSResponse) => C[A]): Future[Either[Result, C[A]]] = { 
    WS.url(url).get().flatMap { response => 
    response.status match { 
     case OK => 
     val data = accumulator ++ parser(response) 

     (response.json \ "paging" \ "next").asOpt[String] match { 
      case None => Future.successful(Right(data)) 
      case Some(next) => pagedRequest(next, data)(parser) 
     } 

     case _ => 
     Future.successful(Left(ProxiedResult(response))) 
    } 
    } 
} 

"데이터"의 유형은 C [A] 대신 반복 가능 [A]로 유지됩니다.

답변

0

문제는 연산자가 CanBuildFrom (암시 적으로 Iterable으로 입력 됨)입니다. 스칼라 소스 TraversableLikeIterable에서

:

def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = { 
    val b = bf(repr) 
    if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size) 
    b ++= thisCollection 
    b ++= that.seq 
    b.result 
    } 

    implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Iterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]] 

그래서 ++의 결과는 Iterable에 입력 된 That입니다. 나는 당신이 할 수있는 것처럼 못생긴 주조없이 여기에서하고 싶은 일을 할 수 있다고 생각하지 않습니다 ...

0

이 작업을 수행하는 유일한 방법은 명백한 유형 변환과 같습니다.

멀 예 :

1) 타입 변환없이 우리는 얻을의 Iterable : 배역와

scala> def addup[A, C[A] <: Iterable[A]](a:C[A],b:C[A])=a ++ b 
addup: [A, C[A] <: Iterable[A]](a: C[A], b: C[A])Iterable[A] 

scala> addup(List(2,3,4,5),List(4,5,6,7)) 
res3: Iterable[Int] = List(2, 3, 4, 5, 4, 5, 6, 7) 

2), 우리는 얻을 C [A] :

scala> def addupC[A, C[A] <: Iterable[A]](a:C[A],b:C[A])=(a ++ b).asInstanceOf[C[A]] 
addupC: [A, C[A] <: Iterable[A]](a: C[A], b: C[A])C[A] 

scala> addupC(List(2,3,4,5),List(4,5,6,7)) 
res4: List[Int] = List(2, 3, 4, 5, 4, 5, 6, 7) 

(A 유사한 문제는 Slick과 같은 라이브러리로 작업 할 때 발생합니다.)

::

def pagedRequest[A, C[A] <: Iterable[A]](url: String, accumulator: C[A])(parser: (WSResponse) => C[A]): Future[Either[Result, C[A]]] = { 
    WS.url(url).get().flatMap { response => 
    response.status match { 
     case OK => 
     val data = (accumulator ++ parser(response)).asInstanceOf[C[A]] 

     (response.json \ "paging" \ "next").asOpt[String] match { 
      case None => Future.successful(Right(data)) 
      case Some(next) => pagedRequest(next, data)(parser) 
     } 

     case _ => 
     Future.successful(Left(ProxiedResult(response))) 
    } 
    } 
}