繁体   English   中英

从类实例导入通用隐式

[英]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错误not enough arguments for method implicitly

如果我直接使用提供程序的隐式val,那么一切都会再次开始工作。

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

但是,我试图避免导入单个值,因为每个提供程序中实际上都有多个隐式对象,目标是在可能的情况下抽象它们。

可以通过某种方式实现,还是我希望编译器提供太多?

问题是,当你从两个对象导入,你就带来两个实体已经发生碰撞的名字: evidenceaProviderevidencebProvider 编译器不能消除它们的歧义,这不仅是因为其实现方式,而且因为对于隐式对象(可能已经是奥秘的)而言,要能够执行无法显式完成的工作(在冲突的名称之间进行歧义化),这不是一个好主意。

我不明白的是ImplicitProvider的意义是什么。 您可以拉动Implementation类向顶层,有一个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._
// ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM