Search code examples
scalagenericsreflectiontype-erasure

Type erasure problem in method overloading


I have two overloaded method having following signatures -

def fun(x: Seq[String]): Future[Seq[Int]] = ???
def fun(x: Seq[(String, String)]): Future[Seq[Int]] = ???

Due to type erasure, these methods can't be overloaded and hence showing compilation error. I tried using typetags as a workaround -

def fun[t: TypeTag](values: Seq[T]): Future[Seq[Int]] = {
    typeOf[T] match {
        case t if t =:= typeOf[String] => ???
        case t if t =:= typeOf[(String, String)] => ???
        case _ => ???    // Should not come here
     }
}

There are two problems with this approach that I am facing -

  1. How can I use the values in the Seq ?
  2. How can I avoid Should not come here case ?

Thanks in advance.


Solution

  • For method overloading you can use

    1. DummyImplicit (see @MarioGalic's answer)

      def fun(x: Seq[String]): Future[Seq[Int]] = ???
      def fun(x: Seq[(String, String)])(implicit ev: DummyImplicit): Future[Seq[Int]] = ???
      
      fun(Seq("a", "b"))
      fun(Seq(("a", "b"), ("c", "d")))
      
    2. type class

      trait FunTypeclass[A] {
        def fun(x: A): Future[Seq[Int]]
      }
      object FunTypeclass {
        implicit val string: FunTypeclass[Seq[String]] = x => ???
        implicit val stringTuple2: FunTypeclass[Seq[(String, String)]] = x => ???
      }
      def fun[A](x: A)(implicit ftc: FunTypeclass[A]): Future[Seq[Int]] = ftc.fun(x)
      
      fun(Seq("a", "b"))
      fun(Seq(("a", "b"), ("c", "d")))
      

    or

    1. magnet

      import scala.language.implicitConversions
      
      trait FunMagnet {
        def fun(): Future[Seq[Int]]
      }
      object FunMagnet {
        implicit def fromString(x: Seq[String]): FunMagnet = () => ???
        implicit def fromStringTuple2(x: Seq[(String, String)]): FunMagnet = () => ???
      }
      def fun(x: FunMagnet): Future[Seq[Int]] = x.fun()
      
      fun(Seq("a", "b"))
      fun(Seq(("a", "b"), ("c", "d")))
      

    Overloading methods based on generics