gpt4 book ai didi

list - Shapeless、Scala 中的过滤器使用

转载 作者:行者123 更新时间:2023-12-02 07:20:18 26 4
gpt4 key购买 nike

很容易按类型过滤无形状的 HList:

val hlist = 1 :: 2 :: "3" :: true :: false :: HNil
hlist.filter[Int]

但是我怎样才能制作我的自定义类型过滤器呢?我想要这样的东西:例如我得到了一些函数的列表:

def function1(s: String) = s.toInt
def function2(s: String) = s.toDouble
def function3(i: Int) = i.toDouble

val hflist = function1 _ :: function3 _ :: function2 _ :: HNil

hflist customFilter[String] //> function1 _ :: function2 _ :: HNil

因此,使用此过滤器后,将构造从 String 类型到其他类型的函数列表。

我有一个想法,使用 map 来实现此目的,但没有成功。

版本

有关我的评论的更多信息:

我尝试在 map 中测试这个想法:

因此,如果我有一些列表(让我们使用 hlisthflist 进行操作):

object allFunction extends Poly1 {
implicit def default[T, M] =
at[T => M](t => {
object grabStringFunc extends skip {
implicit def stringFunc[A] = at[T => A](_ :: HNil)
}

println(hflist flatMap grabStringFunc) //> here we should see result, list of functions
})

hlist map allFunction
//> result of this should be smth like (types)
//> shapeless.::[Int => Double,shapeless.HNil]]
//> shapeless.::[Int => Double,shapeless.HNil]]
//> shapeless.::[String => Int,shapeless.::[String => Double,shapeless.HNil]]
//> shapeless.HNil
//> shapeless.HNil

非常有趣,为什么它编译和运行不正确?我认为这是行不通的,因为对象不能以这种方式接受类型参数......

最佳答案

最简单的方法是使用折叠。首先,我们需要一个多态函数,如果每个项目具有所需的类型(对于某些 A 来说,String => A),它将把每个项目添加到累加器中,否则忽略它:

trait ignore extends Poly2 {
implicit def default[A, L <: HList] = at[A, L]((_, l) => l)
}

object keepStringFunc extends ignore {
implicit def stringFunc[A, L <: HList] = at[String => A, L](_ :: _)
}

现在,以下内容将在 1.2.4 和 2.0.0-M1 中给出您想要的结果:

val filtered = hflist.foldRight(HNil)(keepStringFunc)

您还可以在 FilterFilterAux(或 Filter.Aux)等模型上编写自己的类型类 - 并且如果您想掌握 Shapeless 的窍门,这样做将是一个很好的练习,但 foldRight 要简单得多。

<小时/>

更新:实际上,就其值(value)而言,有一种稍微更简洁的方法可以使用 flatMap 来实现此目的:

trait skip extends Poly1 {
implicit def default[A] = at[A](_ => HNil)
}

object grabStringFunc extends skip {
implicit def stringFunc[A] = at[String => A](_ :: HNil)
}

val filtered = hflist flatMap grabStringFunc

我个人认为 foldRight 版本更明显一点,但这个版本也非常优雅。

<小时/>

回应您的评论:您可以使解决方案更加通用,如下所示:

trait skip extends Poly1 {
implicit def default[A] = at[A](_ => HNil)
}

trait grabFuncFrom[T] extends skip {
implicit def stringFunc[A] = at[T => A](_ :: HNil)
}

object grabStringFunc extends grabFuncFrom[String]

val filtered = hflist flatMap grabStringFunc

但是您仍然需要最后一步,将更高等级的函数创建为对象(例如,请参阅 this answer 和 Miles 的评论,以了解有关此问题的一些讨论)。

关于list - Shapeless、Scala 中的过滤器使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19893633/

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