让我们说我有一个看起来像这样的ADT
sealed trait TT
case class A(...) extends TT
case class B(...) extends TT
case class C(...) extends TT
// ... lot of others
而且我有此函数,它为TT
的子集返回true。假设A
和C
。
def shouldIPublish(tt: TT): Boolean = ???
val shouldIPublishPF: PartialFunction[TT, Unit] = {
case _: A =>
case _: C =>
}
def shouldIPublish(tt: TT): Boolean = shouldIPublishPF.isDefinedAt(tt)
我在这里使用部分函数,因为实际问题要复杂一些。我使用orElse
将几个部分功能组合在一起。
此解决方案易于推论且足够简单。但是,
A
和C
。将新类型添加到部分函数时,我的单元测试应该失败。也许是最简单的解决方案。我可以有一个Set
并使用.getClass
上课。不过看起来很丑。
Set(A.getClass, C.getClass)
起初看起来很有希望。很习惯。
type ShoudIPublish = A :+: C :+: CNil
[不幸的是,我没有看到如何在ShoudIPublish
中测试类型是否“包含”。而且我不知道我们是否可以收集所有类型的列表(此处为A
和C
)。
您有什么建议吗?
类型类看起来像一个解决方案(如果您知道tt
的类型,即在编译时为TT
的特定子类型)
trait ShouldIPublish[T <: TT]
object ShouldIPublish {
implicit val a: ShouldIPublish[A] = null
implicit val c: ShouldIPublish[C] = null
}
def shouldIPublish[T <: TT : ShouldIPublish](tt: T) = ???
shouldIPublish(A())
// shouldIPublish(B()) // doesn't compile
shouldIPublish(C())
标准类型类别为shapeless.ops.coproduct.Inject
type ShoudIPublish = A :+: C :+: CNil
def shouldIPublish[T <: TT : Inject[ShoudIPublish, *]](tt: T) = ???
shouldIPublish(A())
// shouldIPublish(B()) // doesn't compile
shouldIPublish(C())