从 class 个实例中导入泛型隐式

Importing generic implicits from class instances

我正在尝试创建一个通用的隐式提供程序,它可以为给定类型创建一个隐式值,类似于:

trait Evidence[T]

class ImplicitProvider[T] {
  class Implementation extends Evidence[T]
  implicit val evidence: Evidence[T] = new Implementation
}

为了使用这个隐式,我在必要时创建了一个 val provider = new ImplicitProvider[T] 实例并从中导入 import provider._。只要只有一个实例,这就可以正常工作。但是有时在一个地方需要多种类型的隐式

case class A()
case class B()

class Test extends App {
  val aProvider = new ImplicitProvider[A]
  val bProvider = new ImplicitProvider[B]

  import aProvider._
  import bProvider._

  val a = implicitly[Evidence[A]]
  val b = implicitly[Evidence[B]]
}

编译失败,出现 could not find implicit value for parameternot enough arguments for method implicitly 错误。

如果我直接使用提供者的隐式值,一切都会重新开始。

implicit val aEvidence = aProvider.evidence
implicit val bEvidence = bProvider.evidence

但是我试图避免导入单独的值,因为实际上每个提供程序内部都有几个隐含项,目标是尽可能抽象它们。

这能否以某种方式实现,还是我对编译器的要求太多?

问题是,当您从两个对象导入时,您将导入名称冲突的两个实体:aProvider 中的 evidence 和 [=15= 中的 evidence ].编译器无法消除这些歧义,这既是因为它的实现方式,也是因为对于隐式来说,这可能是一个坏主意,它已经很神秘了,能够做一些不能显式完成的事情(消除冲突名称之间的歧义)。

我不明白ImplicitProvider的意义是什么。您可以将 Implementation class 拉出到顶层,并在某个地方放置 object implicit val

class Implementation[T] extends Evidence[T]

object Evidence {
  implicit val aEvidence: Evidence[A] = new Implementation[A]
  implicit val bEvidence: Evidence[B] = new Implementation[B]
}

// Usage:
import Evidence._
implicitly[Evidence[A]]
implicitly[Evidence[B]]

现在,没有名称冲突了。

如果您需要一个实际的 ImplicitProvider,您可以这样做:

class ImplicitProvider[T] { ... }

object ImplicitProviders {
  implicit val aProvider = new ImplicitProvider[A]
  implicit val bProvider = new ImplicitProvider[B]

  implicit def ImplicitProvider2Evidence[T: ImplicitProvider]: Evidence[T]
    = implicitly[ImplicitProvider[T]].evidence
}

// Usage
import ImplicitProviders._
// ...