list – Scala中无形状的过滤器使用情况
很容易按类型过滤HList的形状:
val hlist = 1 :: 2 :: "3" :: true :: false :: HNil hlist.filter[Int] 但是如何制作自定义类型过滤器?我想要那样的smth:例如我得到了一些函数的列表: 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类型到其他类型的函数列表. 我有一个想法,为此使用地图,但它没有成功. 版 有关我的评论的更多信息: 我试图在地图上测试这个想法: 所以,如果我有一些列表(让我们使用hlist和hflist): 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 非常有趣,为什么编译和工作不正确?因为我认为它不起作用,导致对象不能以这种方式采取类型参数… 解决方法
最简单的方法是使用折叠.首先,我们需要一个多态函数,如果它具有所需类型(String => A代表某个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) 你也可以在Filter,FilterAux(或Filter.Aux)等模型上编写你自己的类型类 – 如果你试图搞定Shapeless的话,那么这样做会很好 – 但是foldRight很多简单. 更新:实际上,对于它的价值,使用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的评论,对这个问题进行一些讨论). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |