2012-11-02 3 views
10

에 적용되는 공동/콘트라-차이가 나는이 같은 특성을 가지고 :스칼라 - 암시 적 파라미터 선택

def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B = 
    list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e)) 

: 이런 식으로 작동하는 기능으로

trait CanFold[-T, R] { 
    def sum(acc: R, elem: T): R 
    def zero: R 
} 

의도는 다음과 같습니다.

implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] { 
    def sum(x: Traversable[A], y: Traversable[A]) = x ++ y 
    def zero = Traversable() 
} 

sum(List(1, 2, 3) :: List(4, 5) :: Nil) 
//=> Traversable[Int] = List(1, 2, 3, 4, 5) 

환경을 이미 알고있는 유형의 유형입니다. fold, Ints, Strings에 대해 정의 할 수 있습니다.

내 문제는 내가이 같은 우선권을 더 특정 implicits을 갖고 싶어한다는 것입니다 :

both method CanFoldSeqs in object ... 
and method CanFoldSets in object ... 
match expected type CanFold[Set[Int], B] 

: 모호성 거기로 그 메서드 호출이, 충돌이 발생하지만

implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] { 
    def sum(x: Set[A], y: Set[A]) = x ++ y 
    def zero = Set.empty[A] 
} 

sum(Set(1,2) :: Set(3,4) :: Nil) 
//=> Set[Int] = Set(1, 2, 3, 4) 

그래서 내가 원하는 것은 컴파일러가 Any 형과 My 형을 가장 암시 적으로 검색하는 것입니다. 그 목적은 좀 더 구체적인 하위 유형에 대해 쉽게 겹쳐 쓸 수있는 기본 유형에 대한 기본 구현을 제공하는 것입니다. 섀도 잉은 추악하지 않습니다.

나는 wishfully 여기에 생각을 할 수있어, 그러나 사람은 단지 :-) 기대할 수

이 같은 상황에서 일반적인 접근 방식은 implicits이 상속에 의해 우선 순위 방식을 활용

답변

14

:

trait LowPriorityCanFoldInstances { 
    implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] { 
    def sum(x: Traversable[A], y: Traversable[A]) = x ++ y 
    def zero = Traversable() 
    } 
} 

object CanFoldInstances extends LowPriorityCanFoldInstances { 
    implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] { 
    def sum(x: Set[A], y: Set[A]) = x ++ y 
    def zero = Set.empty[A] 
    } 
} 

import CanFoldInstances._ 

Set 인스턴스가 적용될 때 사용되지만 Traversable 인스턴스는 사용할 수없는 경우에도 계속 사용할 수 있습니다.