Search code examples
scalaimplicitimplicits

How to solve method delegation with scala implicits


How can i solve this simple problem. Class Conversion has a typed method from wich takes two type parameters A and B and returns a B from an A. I have defined some implicits in the companion object to provide default beahviour.

My Problem is when i try to forward the call to the Conversion class within another typed method which has the same signature it does not work. Here in my example i try to forward the call from function myFun to my Conversion class.

I got following error

  • not enough arguments for method from: (implicit f: A => B)

I am wondering why this makes any problems. Can someone explain me why and how to overcome this problem ?

Here is the code

  object MyConversions {

     implicit val IntToStr = (f:Int) => f.toString()

     implicit val DoubleToStr = (f:Double) => f.toString()

     implicit val BooleanToStr = (f:Boolean) => f.toString()

  }

  class Conversions{
     def from[A,B](a:A)(implicit f:(A) => B) = {
       f(a)
     }
  }

  import MyConversions._;

  def myFun[A,B](a:A){
    // Error
    new Conversions().from[A, B](a)
  }

  // Working
  println( new Conversions().from[Int, String](3) )

Solution

  • The problem is that the Scala compiler cannot find an implicit value for the parameter f: (A) => B in the scope of myFun. What you have to do is to tell the compiler that myFun can only be called, when there is such a value available.

    The following code should do the trick

    object App {
      trait Convertible[A, B] {
        def convert(a: A): B
      }
    
      object Convertible {
        implicit val int2String = new Convertible[Int, String] {
          override def convert(a: Int): String = a.toString
        }
    
        implicit val float2String = new Convertible[Float, String] {
          override def convert(a: Float): String = a.toString
        }
      }
    
      def myFun[A ,B](a:A)(implicit converter: Convertible[A, B]): B = {
        converter.convert(a)
      }
    
      def main(args: Array[String]): Unit = {
        println(myFun(3))
      }
    }