如何使用 shapeless 迭代联积中的所有产品类型?

How to iterate all the product types in a coproduct using shapeless?

假设我有一个coproduct(一个密封的特征)比如

sealed trait Traity
case object Foo extends Traity
case class Bar() extends Traity
case class Baz() extends Traity

使用 shapeless,我可以将多态函数应用于特定实例,但我想做的是将零参数(无实例)多态函数应用于所有产品(即案例 类和案例对象)。我不知道语法会是什么样子,但概念上是这样的:

object mypoly extends Poly1 {
  implicit def traity[T <: Traity] = when[T]( getClass[T].toString )
}

iterate[Traity](mypoly) // gives List("Foo", "Bar", "Baz")

适合我的目的。

对于您问题中的示例用例,这实际上非常简单:

import shapeless._

class NameHelper[A] {
  def apply[C <: Coproduct, K <: HList]()(implicit
    gen: LabelledGeneric.Aux[A, C],
    keys: ops.union.Keys.Aux[C, K],
    toSet: ops.hlist.ToTraversable.Aux[K, Set, Symbol]
  ): Set[String] = toSet(keys()).map(_.name)
}

def names[A] = new NameHelper[A]

然后:

scala> names[Traity]()
res0: Set[String] = Set(Bar, Baz, Foo)

(我使用的是 Set,因为您得到的顺序只是按字母顺序排列的——虽然 I'd personally prefer that,但目前无法按声明顺序枚举构造函数。)

如果您想要更通用的答案,对 question I linked above 中的代码进行改编应该不会太糟糕 - 我很乐意稍后将其添加到此处。