我正在尝试创建一个通用的隐式提供程序,它可以为给定的类型创建一个隐式值,如下所示:
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 parameter
和not enough arguments for method implicitly
错误进行编译。
如果我直接使用提供者的隐式val,那么一切都会重新开始。
implicit val aEvidence = aProvider.evidence
implicit val bEvidence = bProvider.evidence
但是我试图避免导入单个值,因为每个提供程序中实际存在几个含义,并且目标是在可能的情况下抽象它们。
这可以通过某种方式实现,还是我想从编译器那里得到太多?
答案 0 :(得分:1)
问题是,当您从这两个对象导入时,您将引入两个具有冲突名称的实体:evidence
中的aProvider
和evidence
中的bProvider
}。编译器无法消除歧义,无论是因为它的实现方式,还是因为它可能已经很神秘,因为它能够执行无法明确完成的事情(消除冲突名称之间的歧义)
我不明白的是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._
// ...