Abstract types of parameters in implicit objects or values?

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])])
//println(splitList(List(1,2,3,4))) //won't compile

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?

+3
source share
1 answer

Scala values ​​(i.e. vals and objects) are monomorphic, so there is no direct way to get what you need if you insist that implications are values.

, : -, , ,

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

scala> splitList(List(("foo",2.0),("bar",3.0)))
res5: (List[java.lang.String], List[Double]) = (List(foo, bar),List(2.0, 3.0))
+4

Source: https://habr.com/ru/post/1788126/


All Articles