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

时间:2017-04-08 11:04:10

标签: scala traits implicit

以下代码无法编译。

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

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的实现中。这样我就可以提供几种实现(测试,生产)。

斯卡拉小提琴在这里:https://scalafiddle.io/sf/dm3OJSF/1

1 个答案:

答案 0 :(得分:2)

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

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

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