gpt4 book ai didi

scala - 在 HList 上做协变过滤器

转载 作者:行者123 更新时间:2023-12-04 18:41:16 24 4
gpt4 key购买 nike

我打算以协变方式过滤 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, 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[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, U, 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.::[Main.Bar,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, 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)
}

(作为记录,您也可以删除 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

我认为这就是你想要的。

关于scala - 在 HList 上做协变过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25713668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com