2012-11-02 22 views
10

Tôi đã có một đặc điểm như thế này:Scala - Co/Contra-Phương sai và đã áp dụng để lựa chọn tham số ngầm

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

Với chức năng làm việc với nó như thế này:

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

Các ý định là làm một việc như sau:

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) 

Vì vậy, đây là loại loại dành cho môi trường đã biết cách gấp và có thể được định nghĩa cho Ints, Strings, bất cứ điều gì.

Vấn đề của tôi là tôi muốn cũng có implicits hơn cụ thể mà được ưu tiên, như thế này:

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) 

Tuy nhiên đó gọi phương pháp tạo ra một cuộc xung đột, như có sự mơ hồ:

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

Vì vậy, những gì tôi muốn là cho trình biên dịch để tìm kiếm tiềm ẩn cụ thể nhất giữa Bất kỳ và loại của tôi. Mục đích là cung cấp việc triển khai mặc định cho các loại cơ sở có thể được ghi đè dễ dàng cho các loại phụ cụ thể hơn mà không bị che khuất.

Tôi chưa wishfully suy nghĩ ở đây, nhưng ta chỉ có thể hy vọng :-)

Trả lời

14

Cách tiếp cận thông thường trong một tình huống như thế này mất lợi thế của cách mà implicits được ưu tiên bởi thừa kế:

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._ 

Hiện tại, phiên bản Set sẽ được sử dụng khi có thể áp dụng, nhưng phiên bản Traversable vẫn khả dụng khi không hoạt động.

Các vấn đề liên quan