让我先解释一下我的用例。我在数据存储区中有一组实体,它们在树结构中相互关联。当增加树形结构中根节点的版本号时,也必须增加相关节点的版本号。
这是实体集
// ADTs
abstract class Versionable[T] { val version: T}
sealed trait PersistableEntity[I] extends Versionable[I] with Product
case class Alpha(version:Int=1) extends PersistableEntity[Int]
case class Beta(version:Int=1) extends PersistableEntity[Int]
case class Gamma(version: Int=1) extends PersistableEntity[Int]
// instances of case classes
val alpha = Alpha()
val beta1 = Beta(100)
val beta2 = Beta(200)
val gamma1 = Gamma(1000)
val gamma2 = Gamma(1100)
val gamma3 = Gamma(1200)
val gamma4 = Gamma(1300)
val gamma5 = Gamma(1400)
我创建了一个类型类来容纳增加版本号的逻辑。如下图所示
sealed trait VersionGenerator[E <:PersistableEntity[_]] {
def createNewVersion(entity:E): E
}
object VersionGenerator {
implicit def persistableEntityVersionGenerator[E <: PersistableEntity[Int]: ClassTag]: VersionGenerator[E] =
new VersionGenerator[E] {
type CC = E {def copy(version: Int): E}
override def createNewVersion(persistableEntity: E): E = persistableEntity match {
case caseClassInstance: CC =>
import scala.language.reflectiveCalls
caseClassInstance.copy(version = persistableEntity.version+1)
case _ => persistableEntity
}
}
}
这些工作正常,因为我能够对其进行验证
val alphaVersionGenerator = implicitly[VersionGenerator[Alpha]]
val betaVersionGenerator = implicitly[VersionGenerator[Beta]]
val gammaVersionGenerator = implicitly[VersionGenerator[Gamma]]
// Output
alphaVersionGenerator: VersionGenerator[Alpha] = com.example.A$A107$A$A107$VersionGenerator$$anon$1@22be8030
betaVersionGenerator: VersionGenerator[Beta] = com.example.A$A107$A$A107$VersionGenerator$$anon$1@309664a7
gammaVersionGenerator: VersionGenerator[Gamma] = com.example.A$A107$A$A107$VersionGenerator$$anon$1@c1464bc
到目前为止,一切都很好。我还创建了一个隐式类,并按如下所示进行了验证
implicit class VersionGenerationOps[E <:PersistableEntity[_]](persistableEntity: E)(implicit evidence: VersionGenerator[E]) {
def newVersion: E = evidence.createNewVersion(persistableEntity)
}
val updatedAlpha = alpha.newVersion
这是输出
updatedAlpha: Alpha = Alpha(2)
类似地,以下内容也适用
def createNewVersions[E <: PersistableEntity[_]](input:E*)(implicit versionGenerator: VersionGenerator[E]): Seq[E] = {
input.map(versionGenerator.createNewVersion)
}
createNewVersions(beta1, beta2, gamma1, gamma2, gamma3, gamma4, gamma5)
// Output
res0: Seq[PersistableEntity[Int] with Serializable] = ArrayBuffer(Beta(101), Beta(201), Gamma(1001), Gamma(1101), Gamma(1201), Gamma(1301), Gamma(1401))
现在是依赖关系树结构的表示形式
// ADT
sealed trait DependencyTree[+E <:PersistableEntity[_]]
case class Branch[+E <:PersistableEntity[_]](value: E, incoming: Set[_<:DependencyTree[_<:PersistableEntity[_]]]) extends DependencyTree[E]
case class Leaf[+E <:PersistableEntity[_]](value: E) extends DependencyTree[E]
以及树形结构中表示的实体之间的关系
val myDependencyTree = Branch(alpha, Set(Leaf(gamma1), Leaf(gamma2),
Branch(beta1, Set(Leaf(gamma3), Leaf(gamma4))),
Branch(beta2, Set(Leaf(gamma5)))
))
只需遍历树即可,如下所示
// Simple traversal
def processDependencyTree[E <: PersistableEntity[_]](input: DependencyTree[E]): Stream[_<: PersistableEntity[_]] = {
def processDependencyTreeBFS[T <: PersistableEntity[_]](accumulator: Stream[_ <: PersistableEntity[_]],
dependencyTree: DependencyTree[T]): Stream[_<: PersistableEntity[_]] = {
import VersionGenerator._
dependencyTree match {
case node@Leaf(entity) =>
println(s"Processing leaf: $entity")
Stream(entity)
case node@Branch(entity, dependencies) =>
println(s"Processing branch: $entity")
val processedChildren:Stream[_<: PersistableEntity[_]] = dependencies
.toSeq
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
.reduce((first, second) => first ++ second)
Stream.cons(entity, processedChildren)
}
}
processDependencyTreeBFS(Stream.empty, input)
}
val result = processDependencyTree(myDependencyTree).toList
// Output
Processing branch: Alpha(1)
Processing leaf: Gamma(1000)
Processing leaf: Gamma(1100)
Processing branch: Beta(100)
Processing leaf: Gamma(1200)
Processing leaf: Gamma(1300)
Processing branch: Beta(200)
Processing leaf: Gamma(1400)
result: List[PersistableEntity[_]] = List(Alpha(1), Gamma(1000), Gamma(1100), Beta(100), Gamma(1200), Gamma(1300), Beta(200), Gamma(1400))
好的,现在出现了问题。如果我引入类型类实例的隐式参数,则由于类型擦除,隐式解析将失败。
这是失败的更新代码
import scala.reflect.runtime.universe._
def processDependencyTree[E <: PersistableEntity[_]](input: DependencyTree[E])
(implicit versionGenerator: VersionGenerator[E], weakTypeTag: WeakTypeTag[E]): Stream[_<: PersistableEntity[_]] = {
def processDependencyTreeBFS[T <: PersistableEntity[_]](accumulator: Stream[_ <: PersistableEntity[_]],
dependencyTree: DependencyTree[T])
(implicit versionGenerator: VersionGenerator[T], weakTypeTag: WeakTypeTag[T]): Stream[_<: PersistableEntity[_]] = {
import VersionGenerator._
dependencyTree match {
case node@Leaf(entity) =>
println(s"Processing leaf: $entity")
Stream(versionGenerator.createNewVersion(entity))
case node@Branch(entity, dependencies) =>
println(s"Processing branch: $entity")
val processedChildren:Stream[_<: PersistableEntity[_]] = dependencies
.toSeq
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
.reduce((first, second) => first ++ second)
Stream.cons(versionGenerator.createNewVersion(entity), processedChildren)
}
}
processDependencyTreeBFS(Stream.empty, input)
}
val result = processDependencyTree(myDependencyTree).toList
这是错误
Error:(84, 88) could not find implicit value for parameter versionGenerator: A$A189.this.VersionGenerator[_$20]
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
Error:(84, 88) not enough arguments for method processDependencyTreeBFS: (implicit versionGenerator: A$A189.this.VersionGenerator[_$20], implicit weakTypeTag: reflect.runtime.universe.WeakTypeTag[_$20])Stream[_ <: A$A189.this.PersistableEntity[_]].
Unspecified value parameters versionGenerator, weakTypeTag.
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
Error:(194, 88) could not find implicit value for parameter versionGenerator: inst$A$A.VersionGenerator[_$33]
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
Error:(194, 88) not enough arguments for method processDependencyTreeBFS: (implicit versionGenerator: inst$A$A.VersionGenerator[_$33], implicit weakTypeTag: reflect.runtime.universe.WeakTypeTag[_$33])Stream[_ <: inst$A$A.PersistableEntity[_]].
Unspecified value parameters versionGenerator, weakTypeTag.
.map( (dt: DependencyTree[_ <: PersistableEntity[_]]) => processDependencyTreeBFS(accumulator, dt) )
对解决隐式分辨率的任何帮助将不胜感激。非常感谢您的时间和精力!
答案 0 :(得分:0)
我找到了答案。由于类型类仅针对特定类型声明,即
E <: PersistableEntity[Int]
要成功解决的隐式参数,还必须与之匹配且不使用
T <: PersistableEntity[_]