2011-01-27 4 views
3

는 내장 객체암시 적 객체 또는 값의 매개 변수 유형을 추상화 하시겠습니까?

trait Splitter[A,B,C] { 
    def split(list: List[C]):(List[A],List[B]) 
} 

implicit object PairSplitter extends Splitter[Int, String, Pair[Int,String]] { 
    override def split(list: List[Pair[Int,String]]):(List[Int],List[String]) = 
    (list.collect{case (a,_) => a}, list.collect{case (_,b) => b}) 
} 

implicit object EitherSplitter extends Splitter[Int, String, Either[Int,String]] { 
    override def split(list: List[Either[Int,String]]):(List[Int],List[String]) = 
    (list.collect{case Left(a) => a}, list.collect{case Right(b) => b}) 
} 

def splitList[A,B,C](list:List[C])(implicit splitter:Splitter[A,B,C]):(List[A],List[B]) = splitter.split(list) 

println(splitList(List((1,"one"),(2,"two"))).isInstanceOf[(List[Int],List[String])]) 
println(splitList(List[Either[Int,String]](Left(42),Right("two"))).isInstanceOf[(List[Int],List[String])]) 
//println(splitList(List(1,2,3,4))) //won't compile 

그것은 작품이 응용 프로그램을 고려하지만, 분명 도움이 끔찍한하지 않습니다. 이 예제에서 Int 및 String과 같은 구체적인 유형에 대해이 값을 쓰는 것은 문제가 없지만 A 및 B에서 추상화하는 암시 적 객체 또는 val을 쓸 방법이 없습니다.

이 작업을 수행 할 수 있으며 어떻게 수행 할 수 있습니까? 그렇지 않은 경우,이 능력을 가진 언어 확장을 기대하는 것이 합리적입니까?

답변

4

스칼라의 값 (즉, vals 및 objects)은 monomorphic이므로 implicits 값을 고집한다면 당신이 원하는 것을 얻는 직접적인 방법은 없습니다.

그러나이 값을 수없는 경우 간단한 대안이있다 : 당신은 다형성이 될 수 뭔가 암시 방법를 사용할 수

implicit def pairSplitter[A, B] = new Splitter[A, B, Pair[A, B]] { 
    override def split(list: List[Pair[A, B]]) : (List[A], List[B]) = 
    (list.collect{case (a,_) => a}, list.collect{case (_,b) => b}) 
} 

REPL 세션 ...

scala> splitList(List(("foo",2.0),("bar",3.0))) 
res5: (List[java.lang.String], List[Double]) = (List(foo, bar),List(2.0, 3.0)) 
+0

D' oh! 어쨌든 두 번째 암시 적 메서드 (둘 중 하나)를 추가 할 때 불명확 한 모호한 오류가 발생할 것이라고 예상했지만 분명히 말도 안되었습니다. 매력처럼 작동합니다! – Landei