2012-11-02 7 views
10

私はこのような特性持っている:それはこのように動作する機能でスカラ - コ/コントラ分散暗黙のパラメータの選択に適用される

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

を:

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

意図は次のようなものです:

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) 

これは、環境がすでにどのように知っているかの型クラスですイント、ストリングスのように定義することができます。

私の問題は、私はまた、このように、優先順位を取るより固有の暗黙を持つようにしたいということです。

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ここで思考することができるんだけど、1だけ

答えて

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のインスタンスは使用できない場合でも使用できます。

関連する問題