scala – 在HList上执行协变过滤器
发布时间:2020-12-16 09:54:54 所属栏目:安全 来源:网络整理
导读:我打算以协变方式过滤HList – 我也希望包含子类.所以Foo上的协变滤波器应该捕获Foo和Bar的元素.我构建了这个例子,尝试:!,看看它是否符合我的意愿. http://scastie.org/6465 /***scalaVersion := "2.11.2"libraryDependencies ++= Seq( "com.chuusai" %% "
我打算以协变方式过滤HList – 我也希望包含子类.所以Foo上的协变滤波器应该捕获Foo和Bar的元素.我构建了这个例子,尝试<:!<,看看它是否符合我的意愿.
http://scastie.org/6465
/*** scalaVersion := "2.11.2" libraryDependencies ++= Seq( "com.chuusai" %% "shapeless" % "2.0.0" ) */ import shapeless._ final class HListOps[L <: HList](l: L) { trait CoFilter[L <: HList,U] extends DepFn1[L] { type Out <: HList } object CoFilter { def apply[L <: HList,U](implicit filter: CoFilter[L,U]): Aux[L,U,filter.Out] = filter type Aux[L <: HList,Out0 <: HList] = CoFilter[L,U] { type Out = Out0 } implicit def hlistCoFilterHNil[L <: HList,U]: Aux[HNil,HNil] = new CoFilter[HNil,U] { type Out = HNil def apply(l: HNil): Out = HNil } implicit def hlistCoFilter1[L <: HList,H](implicit f: CoFilter[L,H]): Aux[H :: L,H,H :: f.Out] = new CoFilter[H :: L,H] { type Out = H :: f.Out def apply(l: H :: L): Out = l.head :: f(l.tail) } implicit def hlistCoFilter2[H,L <: HList,U](implicit f: CoFilter[L,U],e: U <:!< H): Aux[H :: L,f.Out] = new CoFilter[H :: L,U] { type Out = f.Out def apply(l: H :: L): Out = f(l.tail) } } def covariantFilter[U](implicit filter: CoFilter[L,U]): filter.Out = filter(l) } object Main extends App { class Foo(val foo: Int) class Bar(val bar: Int) extends Foo(bar) val l = new Foo(1) :: new Bar(2) :: new Foo(3) :: new Bar(4) :: HNil implicit def hlistOps[L <: HList](l: L): HListOps[L] = new HListOps(l) print(l.covariantFilter[Bar] != l) } 给我 [error] /tmp/rendererbI8Iwy0InO/src/main/scala/test.scala:47: could not find implicit value for parameter filter: _1.CoFilter[shapeless.::[Main.Foo,shapeless.::[Main.Bar,shapeless.::[Main.Foo,shapeless.HNil]]]],Main.Bar] [error] print(l.covariantFilter[Bar] != l) 解决方法
这里有几个问题.第一个是您的类型类是在扩展类中定义的,但是您需要在调用covariantFilter的位置使用该实例.也许编译器可以为你找到它,但事实并非如此.不过,最好不要嵌套类型类.
第二个问题是你的两个hlistCoFilterN案例实际上没有捕获你想要的所有东西.您只告诉编译器在头部类型是过滤器类型以及过滤器类型不是头部类型的子类型的情况下该怎么做.头部的类型在何处是过滤器类型的子类型?你可能想要这样的东西: import shapeless._ trait CoFilter[L <: HList,U] extends DepFn1[L] { type Out <: HList } object CoFilter { def apply[L <: HList,f.Out] = f type Aux[L <: HList,U] { type Out = Out0 } implicit def hlistCoFilterHNil[L <: HList,HNil] = new CoFilter[HNil,U] { type Out = HNil def apply(l: HNil): Out = HNil } implicit def hlistCoFilter1[U,H <: U,T <: HList] (implicit f: CoFilter[T,U]): Aux[H :: T,H :: f.Out] = new CoFilter[H :: T,U] { type Out = H :: f.Out def apply(l: H :: T): Out = l.head :: f(l.tail) } implicit def hlistCoFilter2[U,e: H <:!< U): Aux[H :: T,f.Out] = new CoFilter[H :: T,U] { type Out = f.Out def apply(l: H :: T): Out = f(l.tail) } } implicit final class HListOps[L <: HList](val l: L) { def covariantFilter[U](implicit filter: CoFilter[L,U]): filter.Out = filter(l) } (对于记录,您还可以删除H<:!< U约束并将hlistCoFilter2移动到LowPriorityCoFilter特征.我发现此版本对其意图更清楚一点,但摆脱约束可能会更清晰.) 现在,如果您有以下内容: class Foo(val foo: Int) class Bar(val bar: Int) extends Foo(bar) val l = new Foo(1) :: new Bar(2) :: new Foo(3) :: new Bar(4) :: HNil 您的过滤器将如下工作: scala> l.covariantFilter[Foo] == l res0: Boolean = true scala> l.covariantFilter[Bar] == l res1: Boolean = false 我认为这就是你想要的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |