scala - 用于无形 Hlist 的通用 Poly2 文件夹案例

标签 scala generics fold shapeless hlist

我正在尝试转换以下 HList

Some(C(15)) :: None :: Some(B(55)) :: None :: Some(A(195)) :: HNil


C(15) :: B(55) :: A(195) :: HNil

这是我目前所拥有的:
  import shapeless._
  case class A(value: Int)
  case class B(value: Int)
  case class C(value: Int)

  trait folderLP extends Poly2 {
    implicit def default[T, L <: HList] = at[T, L]((acc, t) => acc)
  }
  object folder extends folderLP {
    implicit def none[T, L <: HList] = at[None.type, L]((t, acc) => acc)

    implicit def someDiameter[T, L <: HList] = at[Some[C], L]((t, acc) => t.get :: acc)

    implicit def someRatio[T, L <: HList] = at[Some[B], L]((t, acc) => t.get :: acc)

    implicit def someWidth[T, L <: HList] = at[Some[A], L]((t, acc) => t.get :: acc)
  }
  val test = Some(C(15)) :: None :: Some(B(55)) :: None :: Some(A(195)) :: HNil

  val filtered = test.foldRight[HList](HNil)(folder)

这有效,但我想让它通用,以便它适用于 Some 中包装的任何类型,而不必编写每个案例

最佳答案

首先是字面的答案。请注意,您的大部分T未使用类型参数。您可以使用该 T使您的函数匹配 Some[T] 类型的任何元素:

trait folderLP extends Poly2 {
  implicit def default[T, L <: HList] = at[T, L]((_, acc) => acc)
}

object folder extends folderLP {
  implicit def some[T, L <: HList] = at[Some[T], L]((t, acc) => t.get :: acc)
}

请注意,您甚至不需要 none如果您在 default 中切换参数顺序的情况.

另请注意,您可能希望使用以下 filtered 的定义:
val filtered = test.foldRight(HNil: HNil)(folder)

这个将有 HNil静态类型为 HNil而不是 HList ,这对于您以后想做的几乎任何事情都非常有用 - 例如尝试 filtered.length在您的原始版本上,然后在此版本上。

不过,您甚至不需要为这个操作折叠——a flatMap会做:
trait filterLP extends Poly1 {
  implicit def any[T] = at[T](_ => HNil)
}

object filter extends filterLP {
  implicit def some[T] = at[Some[T]](_.get :: HNil)
}

进而:
val filtered = test.flatMap(filter)

最后,值得注意的是,这仅适用于 HList哪里NoneSome元素静态类型为 NoneSome —a Some[A]例如,静态类型为 Option[A]会被过滤掉。这使它有点无用(至少我看不到实际用途),但是如果您在编译时不知道 Option 是否可以执行这种类型级过滤器,则实际上没有任何方法可以执行这种类型级别的过滤器。是否为空。

关于scala - 用于无形 Hlist 的通用 Poly2 文件夹案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28591085/

相关文章:

JavaScript:在reduce方法中引用剩余的数组(折叠)?

scala - 链表的用例

performance - 为什么 Scala "for loop comprehensions"与 FOR 循环相比非常慢?

class - 如何制作一个Applet类是单例的Scala Applet?

c# - 如果类型 T 需要实例化,为什么通用类签名需要指定 new() ?

performance - Haskell - foldl' 在 foldr 和性能问题方面

scala - bool 值不可序列化?

c# - 是否有可用于 + 运算符的通用约束?

c# - 如何使用变量将类型传递给泛型方法?

scala - 为什么不将 Nil 传递给 foldLeft 工作?