scala – 将无形HList转换为较小的HList
发布时间:2020-12-16 19:09:51 所属栏目:安全 来源:网络整理
导读:我有一个无形的HList,具有以下结构: type ABCAB = List[A] :: List[B] :: List[C] :: List[A] :: List[B] :: HNilval abcab: ABCAB = List[A]() :: List(B) :: List[C]() :: List(A) :: List(B) :: HNil 我想转换成一个更简单的类型,其中从左到右追加相同类
我有一个无形的HList,具有以下结构:
type ABCAB = List[A] :: List[B] :: List[C] :: List[A] :: List[B] :: HNil val abcab: ABCAB = List[A]() :: List(B) :: List[C]() :: List(A) :: List(B) :: HNil 我想转换成一个更简单的类型,其中从左到右追加相同类型的列表: type ABC = List[A] :: List[B] :: List[C] :: HNil val abc: ABC = abcab.magic // does magic exist in shapeless? abc == List(A) :: List(B,B) :: List[C]() :: HNil // true 为什么在无形v1.2.4中有一些内置功能吗? 解决方法
虽然在另一个答案(引入一个新的类型)中采用的方法将起作用,但是可以使用更通用的机器来解决这个问题 – 并且与在价值水平上解决类似问题的方式没有什么不同.
我们将使用左折.编写组合函数有点棘手,因为我们有两种情况(我们已经看到一个与当前元素具有相同类型的元素,或者我们没有),我们必须使用隐式优先级技巧来避免模糊隐含值: import shapeless._ trait LowPriorityCombine extends Poly2 { implicit def notAlreadySeen[L <: HList,A](implicit p: Prepend[L,List[A] :: HNil] ) = at[L,List[A]](_ :+ _) } object combine extends LowPriorityCombine { implicit def alreadySeen[L <: HList,A](implicit s: Selector[L,List[A]],r: Replacer[L,List[A],List[A]] ) = at[L,List[A]] { case (acc,as) => acc.updatedElem[List[A]](acc.select[List[A]] ++ as) } } 但后来我们基本上完成了: def magic[L <: HList](l: L)(implicit f: LeftFolder[L,HNil.type,combine.type]) = l.foldLeft(HNil)(combine) 我们可以证明它有效: val xs = List(1,2,3) :: List('a,'b) :: List("X","Y") :: List(4,5) :: HNil val test = magic(xs) 然后: scala> test == List(1,3,4,5) :: List('a,"Y") :: HNil res0: Boolean = true 正如所料. 上面的代码是针对1.2.4编写的,但它应该在2.0上进行一些非常小的修改. 更新:记录,这是2.0的工作版本: import shapeless._,ops.hlist.{ LeftFolder,Prepend,Replacer,Selector } trait LowPriorityCombine extends Poly2 { implicit def notAlreadySeen[L <: HList,A,Out <: HList](implicit p: Prepend.Aux[L,List[A] :: HNil,Out] ): Case.Aux[L,Out] = at[L,Out <: HList](implicit s: Selector[L,r: Replacer.Aux[L,(List[A],Out)] ): Case.Aux[L,as) => acc.updatedElem[List[A],Out](acc.select[List[A]] ++ as) } } def magic[L <: HList](l: L)(implicit f: LeftFolder[L,HNil,combine.type]) = l.foldLeft(HNil: HNil)(combine) 主要区别在于新导入,但由于updatedElem上的额外类型参数,您还需要进行一些其他小的更改. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- [AngularJS面面观] 23. 依赖注入 --- Factory vs Service
- arrays – 使用IFS将字符串Bash转换为数组
- Vim正在触发多次保存
- 维护了这么久的服务器,你真的认识 Web 缓存体系?
- Scala的mutable.ListBuffer似乎使用了List的尾部函数,但它被
- 通过Cygwin创建的文件(调用shell脚本)没有正确的Windows权限
- twitter-bootstrap – 如何通过webpack 2从bootstrap 4中仅
- AngularJS:textarea和ng-repeat-ed输入之间的双向绑定
- 如何在OpenLDAP中启用GPG / PGP密钥的存储
- angularjs – 不同类型的角度指令模式