基本上,我想要转置我的对象。有没有简单的方法可以做到这一点?如果我的HList很大,我不想折叠。
这是为了解压一个高元组的列表。
发布于 2018-03-09 07:33:21
我不知道现有的解决方案,但这似乎是一个有趣的任务,所以我尝试了一下。
假设我们有一个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列表并使用Poly2合并HLists来实现HLists。
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 (并且是正确的类型)。
https://stackoverflow.com/questions/49182575
复制相似问题