从 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 parameter
和 not 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._
// ...
我正在尝试创建一个通用的隐式提供程序,它可以为给定类型创建一个隐式值,类似于:
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
错误。
如果我直接使用提供者的隐式值,一切都会重新开始。
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._
// ...