gpt4 book ai didi

scala - 为密封特征创建类型类实例

转载 作者:行者123 更新时间:2023-12-04 19:41:32 25 4
gpt4 key购买 nike

假设我有一个“宽”的密封类层次结构:

sealed trait Alphabet
case class A(word: String) extends Alphabet
...
case class Z(word: String) extends Alphabet

假设我为层次结构中的每个子类定义了一个类型类实例:
trait SwearWordFinder[T <: Alphabet] {
def isSwearWord(x: T): Boolean
}

val swearWordFinderA = new SwearWordFinder[A] { ... }
...
val swearWordFinderZ = new SwearWordFinder[Z] { ... }

有没有办法为 Alphabet 定义类型类实例? trait 本身而不必通过模式匹配来实现它(如下)?
def isSwearWord(x: Alphabet): Boolean = x match {
case a: A => swearWordFinderA.isSwearWord(a)
...
case z: Z => swearWordFinderZ.isSwearWord(z)
}

最佳答案

您可以代表Alphabet作为无形CoproductA :+: B :+: ... :+: Z :+: CNil ,所以如果你有 SwearWordFinder A 的实例, B , ... 并为 CNil 定义实例和 :+:你可以得到一个 SwearWordFinder[Alphabet]使用其通用表示。

import shapeless._

trait SwearWordFinder[T] {
def isSwearWord(x: T): Boolean
}

object SwearWordFinder extends SwearWordFinder0 {
implicit def apply[T](implicit swf: SwearWordFinder[T]): SwearWordFinder[T] = swf

implicit val cnilSwearWordFinder: SwearWordFinder[CNil] =
new SwearWordFinder[CNil] {
def isSwearWord(t: CNil): Boolean = false
}

implicit def coproductConsSwearWordFinder[L, R <: Coproduct](implicit
lSwf: SwearWordFinder[L],
rSwf: SwearWordFinder[R]
): SwearWordFinder[L :+: R] =
new SwearWordFinder[L :+: R] {
def isSwearWord(t: L :+: R): Boolean =
t.eliminate(lSwf.isSwearWord, rSwf.isSwearWord)
}
}

trait SwearWordFinder0 {
implicit def genericSwearWordFinder[T, G](implicit
gen: Generic.Aux[T, G],
swf: Lazy[SwearWordFinder[G]]
): SwearWordFinder[T] =
new SwearWordFinder[T] {
def isSwearWord(t: T): Boolean = swf.value.isSwearWord(gen.to(t))
}
}

现在我们的信件的一些实例:
sealed trait Alphabet extends Product with Serializable

object Alphabet {
final case class A(word: String) extends Alphabet
final case class Z(word: String) extends Alphabet
}

implicit val swfA = new SwearWordFinder[Alphabet.A] {
def isSwearWord(a: Alphabet.A) = a.word == "apple"
}

implicit val swfZ = new SwearWordFinder[Alphabet.Z] {
def isSwearWord(z: Alphabet.Z) = z.word == "zebra"
}

现在我们可以得到一个 SwearWordFinder[Alphabet] :
def isBadWord[T](t: T)(implicit swfT: SwearWordFinder[T]): Boolean = 
swfT.isSwearWord(t)

val a1: Alphabet = Alphabet.A("apple")
val z2: Alphabet = Alphabet.Z("zorro")
val z3: Alphabet = Alphabet.Z("zebra")

isBadWord(a1) // true
isBadWord(z2) // false
isBadWord(z3) // true

就像我在评论中提到的:提防 SI-7046 .您的 Alphabet AST 需要在一个项目中,该项目带有 SwearWordFinder依赖或在一个包中,该包将在具有 Alphabet 的类型类派生的包之前编译.

关于scala - 为密封特征创建类型类实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38073716/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com