Search code examples
scalaimplicits

Scala implicit not found "not enough arguments"


In this simple code i have a method buildResponse which takes a type parameter T which must be a subtype of Response.

Now the compiler tells me it does not find an implicit value when i call new ResponseBuilder().build\[T]() inside alltough i have defined an implicit for class Response in the Builder companion object.

I thought due T must be a subtype of Response it will take the implicit value for Builder[Response]. If T would be something else then Response i would have excpected this error.

So whats the right way to get this done ?

import scala.util.Try;

object Main extends App {



  case class Response(val v:String){

  }

  sealed trait Builder[T] {
    def build(): Try[T]
  }

  object Builder {
    implicit val BuilderResponse = new Builder[Response] {
      def build(): Try[Response] = {
        Try {
          Response("Hello")
        }
      }
    }

    implicit val BuilderInt = new Builder[Int] {
      def build(): Try[Int] = {
        Try {
          1
        }
      }
    }
  }

  class ResponseBuilder
  {
    def build[T:Builder]() : Try[T] = {
       implicitly [Builder[T]].build()
    }
  }

  // works fine
  //new ResponseBuilder().build[Response]();


  //not enough arguments for method build: (implicit evidence$1: Main.Builder[T])scala.util.Try[T]. Unspecified value parameter evidence$1.
  def buildResponse[T <: Response ]() : Try[T] = {
    new ResponseBuilder().build[T]();
  }


}

Solution

  • The problem is not that you need an implicit value of type Builder[Response] but of type Builder[T]. The implicit value BuilderResponse: Builder[Response] cannot be used here because T can be any subtype of Response.

    You can make the code compiling by either adding a Builder context bound to your method buildResponse

    def buildResponse[T <: Response: Builder]() : Try[T] = {
      new ResponseBuilder().build[T]();
    }
    

    Or by defining an implicit method createBuilder[T <: Response]: Builder[T] in the Builder companion object which generates the Builder objects somehow.

    implicit def createBuilder[T <: Response]: Builder[T] = ...