加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何在HLists上实现zipWithIndex

发布时间:2020-12-16 18:12:46 所属栏目:安全 来源:网络整理
导读:在HList上编写算法,我需要一个zipWithIndex函数.它现在不在无形图书馆,所以我决定实施它. 很明显它可能被实现为 hlist.zip(indexes) 其中索引是索引的HList(0..n),这可能是通过这种方式获得的: val indexes = Nat._0 until hlist.length 这里的问题是Nat直
在HList上编写算法,我需要一个zipWithIndex函数.它现在不在无形图书馆,所以我决定实施它.

很明显它可能被实现为

hlist.zip(indexes)

其中索引是索引的HList(0..n),这可能是通过这种方式获得的:

val indexes = Nat._0 until hlist.length

这里的问题是Nat直到方法才有.我没有找到任何与HList.map一起使用的HList索引的Witness.

从Nat._0开始直到hlist.length,我可以使用什么方法来获取Nats的NList?

解决方法

向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,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)

您还可以使用折叠或ZippedWithIndex [L<:HList]类型类,这两种类型可能更简洁,但不太清楚,由Range等独立有用的部分组成.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读