2011-01-27 163 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这样的具体类型编写这个没什么问题,但是我看不出有什么办法可以编写一个隐含的对象或val,它通过A和B抽象。

可以这样做吗?如果没有,期望有这种能力的语言扩展是否合理?

回答

4

斯卡拉的值(即瓦尔和对象)是单形,所以如果你坚持作为值的含义是没有直接的方式来获得你的。

但是有,如果他们没有要值一个简单的选择:你可以使用一些东西,可以是多态的,隐式方法

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!不知何故,当我添加第二个隐式方法(对于Either)时,我预料会得到臭名昭着的模棱两可的错误,但显然这是无稽之谈。奇迹般有效! – Landei 2011-01-27 10:09:48