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

scala – Shapeless:在HList上反转filterNot

发布时间:2020-12-16 18:51:05 所属栏目:安全 来源:网络整理
导读:我正在尝试为scodec库编写一个组合器,它将Codec [K]转换为Codec [L],其中K是HList,L是删除了所有Unit元素的等效HList. 实现解码可以通过解码K然后滤除所有单元元素来完成.使用filterNot可以无形地直接过滤掉单元元素,这使得实现这一点变得微不足道. 实现编码
我正在尝试为scodec库编写一个组合器,它将Codec [K]转换为Codec [L],其中K是HList,L是删除了所有Unit元素的等效HList.

实现解码可以通过解码K然后滤除所有单元元素来完成.使用filterNot可以无形地直接过滤掉单元元素,这使得实现这一点变得微不足道.

实现编码是通过将L转换为K,在适当的索引处插入(),然后委托给原始的Codec [K]来完成的.我无法实现L => K转换虽然.

def dropUnits[K <: HList,L <: HList](codec: Codec[K])(
  implicit fltr: FilterNot.Aux[K,Unit,L]): Codec[L] = new Codec[L] {
    override def decode(buffer: BitVector) = 
        codec.decode(buffer).map { case (rest,l) => (rest,l.filterNot[Unit]) }
    override def encode(xs: L) = {
      ???
    }
  }

没有运气,我尝试了几种不同的解决方案.这可能是无形的吗?

解决方法

没有自定义类型类,我没有看到这样做的方法,但这种方法并不太糟糕:

import shapeless._

trait ReUnit[L <: HList,K <: HList] { def apply(l: L): K }

object ReUnit {
  implicit object hnilReUnit extends ReUnit[HNil,HNil] {
    def apply(l: HNil): HNil = HNil
  }

  implicit def hlistReUnit[H,L <: HList,K <: HList]
    (implicit ru: ReUnit[L,K]): ReUnit[H :: L,H :: K] =
      new ReUnit[H :: L,H :: K] {
        def apply(l: H :: L): H :: K = l.head :: ru(l.tail)
      }

  implicit def unitReUnit[L <: HList,K]): ReUnit[L,Unit :: K] =
       new ReUnit[L,Unit :: K] {
         def apply(l: L): Unit :: K = () :: ru(l)
       }
}

def reUnit[L <: HList,K <: HList](l: L)(implicit ru: ReUnit[L,K]) = ru(l)

然后:

scala> type Input = Int :: String :: HNil
defined type alias Input

scala> type WithUnits = Int :: Unit :: String :: Unit :: Unit :: HNil
defined type alias WithUnits

scala> reUnit[Input,WithUnits](1 :: "foo" :: HNil)
res0: WithUnits = 1 :: () :: foo :: () :: () :: HNil

或者在您的背景下:

def dropUnits[K <: HList,L <: HList](codec: Codec[K])(implicit
  fn: FilterNot.Aux[K,L]
  ru: ReUnit[L,K]
): Codec[L] = new Codec[L] {
  override def decode(buffer: BitVector) = 
    codec.decode(buffer).map { case (rest,l.filterNot[Unit]) }
  override def encode(xs: L) = codec.encode(ru(xs))
}

我没有尝试编译这个dropUnits但它应该工作.

上面的诀窍就是努力实现你想要的实例.基本情况是将HNil转换为HNil.然后,如果你知道如何将X转换为Y,你也知道如何做两件事:将A :: X转换为A :: Y并将X转换为Unit :: Y.这就是你需要的全部!

(编辑:李大同)

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

    推荐文章
      热点阅读