Позвольте мне сначала объяснить мой вариант использования.У меня есть набор сущностей в хранилище данных, которые связаны друг с другом в древовидной структуре.Когда номер версии корневого узла в древовидной структуре увеличивается, номера версий связанных узлов должны быть увеличены.
Вот набор сущностей
// 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) )
Любая помощь в исправлении неявного разрешения будет искренне признательна.Заранее большое спасибо за ваше время и усилия!