覆盖特征中的隐式抽象成员 - 隐式依赖注入(类型 class 实例) - 如何使其工作?

overriding implicit abstract members in a trait - injection of implicit dependencies (type class instances) - how to make it work?

下面的代码编译失败。

此代码的目的是将隐式依赖项注入 UseImplicit。 换句话说,它是类型 class 实例的依赖注入。

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]

}

但这编译得很好:

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
}

我看不出这两个代码有什么区别,它们具有相同的结构。

为什么第二个可以编译而第一个不能?

如何进行第一次编译?

目标是我可以将隐式注入到 UseImplicits 的实现中。这样我就可以提供几个实现(测试,生产)。

Scala Fiddle 在这里:https://scalafiddle.io/sf/dm3OJSF/1

在调用 UI.foo() 之前将 UI 隐含(通过 import UI._)导入当前范围应该可以解决您的问题。


您可以注入所需的 UseImplicit(例如注入 Foo class)并将其用作:

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