簡體   English   中英

如何在HLists上實現zipWithIndex

[英]How to implement zipWithIndex on HLists

HListHList算法,我需要一個zipWithIndex函數。 它現在不在無形圖書館,所以我決定實施它。

很明顯它可能被實現為

hlist.zip(indexes)

其中indexesindexesHList (0..n),這可能是通過這種方式獲得的:

val indexes = Nat._0 until hlist.length

這里的問題是Nat until方法until 我還沒有發現任何WitnessHList指數與使用HList.map

什么是我可以用它來獲得方法HListNat首發與Nat._0直到hlist.length

向Shapeless添加這樣的東西可能是有意義的:

import shapeless._, ops.hlist.Prepend

trait Range[A <: Nat, B <: Nat] extends DepFn0 { type Out <: HList }

object Range {
  type Aux[A <: Nat, B <: Nat, Out0 <: HList] = Range[A, B] { type Out = Out0 }

  implicit def emptyRange[A <: Nat]: Aux[A, A, HNil] = new Range[A, A] {
    type Out = HNil
    def apply(): Out = HNil
  }

  implicit def slightlyBiggerRange[A <: Nat, B <: Nat, OutAB <: HList](implicit
    rangeAB: Aux[A, B, OutAB],
    appender: Prepend[OutAB, B :: HNil],
    witnessB: Witness.Aux[B]
  ): Aux[A, Succ[B], appender.Out] = new Range[A, Succ[B]] {
    type Out = appender.Out
    def apply(): Out = appender(rangeAB(), witnessB.value :: HNil)
  }
}

def range[A <: Nat, B <: Nat](implicit r: Range[A, B]): r.Out = r()

現在你可以非常干凈地編寫zipWithIndex

import ops.hlist.{ Length, Zip }

def zipWithIndex[L <: HList, S <: Nat, R <: HList, Out <: HList](l: L)(implicit
  len: Length.Aux[L, S],
  range: Range.Aux[nat._0, S, R],
  zipper: Zip.Aux[L :: R :: HNil, Out]
): Out = l.zip(range())

然后:

import nat._

type Expected = (Int, _0) :: (Symbol, _1) :: (String, _2) :: HNil

val xs: Expected = zipWithIndex(1 :: 'a :: "foo" :: HNil)

你也可以使用fold或ZippedWithIndex[L <: HList]類型類,這兩個類都可能更簡潔,但不太清楚,由Range等獨立有用的部分組成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM