【问题标题】:How to iterate all the product types in a coproduct using shapeless?如何使用无形迭代副产品中的所有产品类型?
【发布时间】:2015-04-16 13:27:51
【问题描述】:

假设我有一个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")

适合我的目的。

【问题讨论】:

  • 我目前无法提供完整的答案,但您可以查看我的问题here,该问题提供了类似问题的解决方案——您只需更改@ 987654325@类型类。
  • @TravisBrown 谢谢!我想这会获取所有实例(Witness 正在抓取它们,对吗?),但我真的只关心类型。也许这意味着我的def coproductX 会更简单......
  • 实际上,您的问题/答案本身就非常有用!

标签: scala shapeless


【解决方案1】:

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

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 中的代码进行改编应该不会太糟糕——我很乐意稍后在此处添加。

【讨论】:

  • 如何更改代码以取回Set[A],即所有可用实例的集合?
  • @sschaef 如果您只有案例对象,那么最后一句链接中的代码现在应该可以正常工作了。如果您还有不带参数的案例类,则需要调整 AllSingletons 类型类。
  • 是的,该代码工作正常,谢谢。我只是想知道是否可以在这个答案中用A 替换Symbol 并立即获得所有需要的隐式。
  • @sschaef 不,不幸的是,从类型到实例需要更多的工作。
  • 虽然链接问题中的代码运行良好,但我发现我可能无法在实际应用程序中使用它,因为它具有指数编译时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多