0
votes

The code below fails to compile.

The purpose of this code is to inject the implicit dependencies into UseImplicit. In other words, it is a dependency injection for type class instances.

trait StuffProvider[T]{
  implicit val provideStuff:() => T
}

trait UseImplicit{
  implicit val gimmiString: StuffProvider[String] // implicit dependency
  implicit val gimmiInt: StuffProvider[Int]
  def foo[T:StuffProvider]() :T = implicitly[StuffProvider[T]].provideStuff()
}

object Main{

  object StringProvider extends StuffProvider[String]{
    implicit val provideStuff: () => String= () => "bla"
  }

  object IntProvider extends StuffProvider[Int]{
    implicit val  provideStuff: () => Int= () => 42
  }

  object UI extends UseImplicit {
    implicit val gimmiString=StringProvider // injection
    implicit val gimmiInt=IntProvider
  }

  val f:Int=UI.foo[Int]() //  Error:(27, 15) could not find implicit value for evidence parameter of type StuffProvider[T]

}

but this compiles just fine :

trait UseImplicit2{
  implicit val gimmiString: String
  def foo() :String = implicitly[String]
}

object Main2{

  object UI extends UseImplicit2 {
    override implicit val gimmiString:String = "s"
  }
  val f=UI.foo() // this compiles just fine
}

I don't see what is the difference between the two codes, they have the same structure.

Why does the second compile and the first not ?

How can I make the first compile ?

The goal is that I can inject the implicits into a realization of UseImplicits. So that I can provide several realizations (testing, production).

Scala Fiddle is here : https://scalafiddle.io/sf/dm3OJSF/1

1

1 Answers

2
votes

Importing UI implicits (by import UI._) into current scope, right before calling UI.foo(), should fix your issue.


You can inject the desired UseImplicit (e.g into a Foo class) and use it as:

case class Foo(ui: UseImplicit) {
  import ui._
  val f: Int = ui.foo[Int]() //Use your injected `UseImplicit`
}