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

邮差的信 提交于 2019-12-03 17:31:35

问题


Let's say I have a coproduct (a sealed trait) such as

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

Using shapeless, I can apply polymorphic functions to specific instances but what I'd like to do is to apply a zero-parameter (no-instance) polymorphic function to all the products (i.e. case classes and case objects). I have no idea what the syntax would look like, but something conceptually like:

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

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

would suit my purposes.


回答1:


For the example use case in your question, this is actually very straightforward:

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]

And then:

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

(I'm using a Set since the order you're getting is just alphabetical—it's not currently possible to enumerate the constructors in declaration order, although I'd personally prefer that.)

If you'd like a more generic answer, an adaptation of the code in the question I linked above shouldn't be too bad—I'd be happy to add it here later.



来源:https://stackoverflow.com/questions/29676204/how-to-iterate-all-the-product-types-in-a-coproduct-using-shapeless

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!