Scala 在HList上执行协变过滤器
我打算以协变的方式对HList进行过滤——我也想包括子类。因此Scala 在HList上执行协变过滤器,scala,shapeless,Scala,Shapeless,我打算以协变的方式对HList进行过滤——我也想包括子类。因此Foo上的协变过滤器应该捕获Foo以及Bar的元素。我构建了这个示例,尝试这里有几个问题。首先,您的类型类是在扩展类内部定义的,但是您需要在调用convaratitfilter时使用实例。也许编译器可以为您找到它,但它没有。不过,无论如何,不嵌套类型类要干净得多 第二个问题是,您的两个hlistCoFilterN案例实际上并没有捕获您想要的所有内容。只有在头的类型是过滤器类型,而过滤器类型不是头类型的子类型的情况下,您才告诉编译器该怎
Foo
上的协变过滤器应该捕获Foo
以及Bar
的元素。我构建了这个示例,尝试这里有几个问题。首先,您的类型类是在扩展类内部定义的,但是您需要在调用convaratitfilter
时使用实例。也许编译器可以为您找到它,但它没有。不过,无论如何,不嵌套类型类要干净得多
第二个问题是,您的两个hlistCoFilterN
案例实际上并没有捕获您想要的所有内容。只有在头的类型是过滤器类型,而过滤器类型不是头类型的子类型的情况下,您才告诉编译器该怎么做。头部类型是过滤器类型的子类型的位置如何?你可能想要这样的东西:
import shapeless._
trait CoFilter[L <: HList, U] extends DepFn1[L] { type Out <: HList }
object CoFilter {
def apply[L <: HList, U](implicit f: CoFilter[L, U]): Aux[L, U, f.Out] = f
type Aux[L <: HList, U, Out0 <: HList] = CoFilter[L, U] { type Out = Out0 }
implicit def hlistCoFilterHNil[L <: HList, U]: Aux[HNil, U, 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, U, 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, H, T <: HList]
(implicit f: CoFilter[T, U], e: H <:!< U): Aux[H :: T, U, 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)
}
scala> l.covariantFilter[Foo] == l
res0: Boolean = true
scala> l.covariantFilter[Bar] == l
res1: Boolean = false
您的过滤器的工作方式如下:
import shapeless._
trait CoFilter[L <: HList, U] extends DepFn1[L] { type Out <: HList }
object CoFilter {
def apply[L <: HList, U](implicit f: CoFilter[L, U]): Aux[L, U, f.Out] = f
type Aux[L <: HList, U, Out0 <: HList] = CoFilter[L, U] { type Out = Out0 }
implicit def hlistCoFilterHNil[L <: HList, U]: Aux[HNil, U, 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, U, 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, H, T <: HList]
(implicit f: CoFilter[T, U], e: H <:!< U): Aux[H :: T, U, 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)
}
scala> l.covariantFilter[Foo] == l
res0: Boolean = true
scala> l.covariantFilter[Bar] == l
res1: Boolean = false
我想这就是你想要的。如果你能解释一下你想做什么,这个问题会好得多。乍一看,我不知道你为什么希望hlistCoFilterN
给你想要的实例(不是Foo=:=Bar
或Bar@TravisBrown都是好的观点。啊,你不想检查l.convaratitfilter[Foo]
,那么?@TravisBrown这是应该满足要求的方法,所以我想测试它。hlistCoFilter2
的要求是必要的吗?反正应该是默认的。你是说
scala> l.covariantFilter[Foo] == l
res0: Boolean = true
scala> l.covariantFilter[Bar] == l
res1: Boolean = false