Consider this application of implicit objects
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])])
This works, but obviously not terribly useful. There is no point in writing this for specific types, such as Int and String in the example, but I see no way to write an implicit object or val that abstracts over A and B.
Can this be done and how? If not, is it reasonable to expect an extension of the language with this ability?