Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call an overloaded method from a generic type

Tags:

scala

I have this set of overloaded functions:

case class A[T](t: T)

object C {
   def dump(a: A[String], s: String) = ....
   def dump(a: A[Int], s: Int) = ....
   def dump(a: A[Double], s: Double) = ....
}

and have this generic method:

class B {
   def dump[T](a: A[T], t: T) = C.dump(a, t)
}

It doesn't compile, because the Scala compiler gets confused with the different overloads. What is the right way of doing it?

like image 407
david.perez Avatar asked Mar 20 '23 01:03

david.perez


2 Answers

edit: The problem with your implementation is, that at compile time it does not know which version of C.dump it should use, because it only know that there is some type T, but it can't possibly know what type it will hold when the method is actually being used.


You can solve this using ad-hoc polymorphism:

trait Dumper[A] {
  def dump(a: A): Unit
}

case class A[T](t: T)

object A {
  implicit object AStringDumper extends Dumper[A[String]] {
    def dump(a: A[String]) = println(s"String: $a")
  }

  implicit object ADoubleDumper extends Dumper[A[Double]] {
    def dump(a: A[Double]) = println(s"Double: $a")
  }
}

object C {
  def dump[A](a: A)(implicit dumper: Dumper[A]) = dumper.dump(a)
}

The compiler will try to find an instance of Dumper[A] when you call C.dump. If it can't find one, it will not compile:

scala> C.dump(A("foo"))
String: A(foo)

scala> C.dump(A(1.2))
Double: A(1.2)

scala> C.dump(A(1))
<console>:17: error: could not find implicit value for parameter dumper: Dumper[A[Int]]
              C.dump(A(1))
like image 135
drexin Avatar answered Mar 21 '23 18:03

drexin


Based on @drexin answer by using ad-hoc polymorphism, I just slightly change to use the signature of the question to make it a little bit more clear.

def dump[T](a: A[T], t: T) = C.dump(a, t)

case class A[T](t: T)
trait Dumper[T] {
  def dump(a: A[T], t: T): Unit
}
class B {
  def dump[T](a: A[T], t: T)(implicit dumper: Dumper[T]) = dumper.dump(a, t)
}
implicit val IntDummper = new Dumper[Int] {
  override def dump(a: A[Int], t: Int): Unit = {
    println("int dummper processing it")
  }
}

implicit val StringDummper = new Dumper[String] {
  override def dump(a: A[String], t: String): Unit = {
    println("string dummper processing it")
  }
}

val result = new B

result.dump(A("3"), "3") //string dummper processing it
result.dump(A(3), 3) //int dummper processing it
like image 32
Xiaohe Dong Avatar answered Mar 21 '23 19:03

Xiaohe Dong