如何使用 shapeless 迭代联产品中的所有产品类型? [英] How to iterate all the product types in a coproduct using shapeless?

查看:25
本文介绍了如何使用 shapeless 迭代联产品中的所有产品类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 coproduct(一个密封的特性)例如

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

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

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")

符合我的目的.

推荐答案

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

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]

然后:

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

(我正在使用 Set,因为您获得的顺序只是按字母顺序排列的 - 目前无法按声明顺序枚举构造函数,尽管 我个人更喜欢这个.)

(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.

这篇关于如何使用 shapeless 迭代联产品中的所有产品类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆