2011-01-27 9 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

Scalaの値(すなわち。ヴァルスとオブジェクトが)単形なので、あなたがた値であること暗黙に主張すれば、あなたが後にしているものを得るの直接的な方法はありません。

しかし、彼らが値であることが持っていない場合、簡単な選択肢があります:あなたは多形することができ何か、暗黙の方法を使用することができ、

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!どういうわけか、私は2番目の暗黙のメソッド(どちらか一方のために)を追加すると悪名高い曖昧なエラーが出ると思っていましたが、明らかにそれはナンセンスでした。魅力的な作品! – Landei

関連する問題