HL列表到列表的列表?

时间:2018-03-08 21:15:09

标签: scala shapeless

基本上我想转置我的对象。有一个简单的方法吗?如果我的HList很大而且我不想弃牌。

这是解压缩高级元组列表的服务。

1 个答案:

答案 0 :(得分:0)

我不知道现有的解决方案,但这似乎是一项有趣的任务,所以我尝试了它。

假设我们有一个HLists列表,比如

val myList: List[Int :: String :: Boolean :: HNil] = List(
  1 :: "sample1" :: true :: HNil,
  2 :: "sample2" :: false :: HNil,
  3 :: "sample3" :: true :: HNil
)

我们想要一个列表的HList,比如

val expected: List[Int] :: List[String] :: List[Boolean] :: HNil = 
  List(3, 2, 1) :: 
  List("sample3", "sample2", "sample") :: 
  List(true, false, true) ::
  HNil

我们需要创建一个类型类。我把它命名为EmptyOf。它有一个方法可以创建一个包含空列表的HList。

trait EmptyOf[T <: HList, AsList <: HList] {
  def empty: AsList
}

这是HNil的实现:

implicit val emptyOfHNil: EmptyOf[HNil, HNil] = () => HNil

现在对于HCons:

implicit def emptyOfHCons[H, T <: HList, TEmpty <: HList](
  implicit ev: EmptyOf[T, TEmpty]
): EmptyOf[H :: T, List[H] :: TEmpty] = () => List.empty[H] :: ev.empty()

因此,对于EmptyOf[T :: U :: HNil, List[T] :: List[U] :: HNil],我们的实例empty将返回Nil :: Nil :: HNil

通过这些,我们可以通过折叠HLists列表并使用transpose来合并HLists来实现Poly2

object concat extends Poly2 {
  implicit def prepend[S] = at[List[S], S]((list, s) => s :: list)
}

def transpose[T <: HList, U <: HList](lists: List[T])
                                     (implicit emptyOf: EmptyOf[T, U],
                                      zip: ZipWith.Aux[U, T, concat.type, U]): U =
  lists.foldLeft(emptyOf.empty())(_.zipWith(_)(concat))

现在transpose(myList)应该等于expected(以及正确的类型)。