在不成形的过滤器中使用Scala [英] Filter usage in shapeless, Scala

查看:151
本文介绍了在不成形的过滤器中使用Scala的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 很容易过滤 HList  > val hlist = 1 :: 2 ::3:: true :: false :: HNil 
hlist.filter [Int]

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

$ $ p $ def $ function def(s:String)= s.toInt
def function2(s:String)= s.toDouble
def function3(i:Int)= i.toDouble
$ b $ val hflist = function1 _ :: function3 _ :: function2 _ :: HNil

hflist customFilter [String] //>因此,在使用此过滤器之后,函数列表中的函数列表将显示在函数列表中。 字符串到其他类型将被构造。



我有一个使用map的想法,但这不是成功的。



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



我试图在map中测试这个想法: / p>

所以如果我有一些列表(让我们用 hlist & hflist
$ p $ object allFunction extends Poly1 {
implicit def default [T,M] = $ b $ T在[T => M](t => {
object grabStringFunc extends skip {
implicit def stringFunc [A] = at [T => A](_ :: HNil)
}

println(hflist flatMap grabStringFunc)//> //这里我们应该看到结果,函数列表
})

hlist map allFunction
//>结果应该是(类型)
//> shapeless.::[Int => Double,shapeless.HNil]]
//> shapeless.::[Int => Double,shapeless.HNil]]
//> shapeless.::[String => Int,shapeless。:: [String => Double,shapeless.HNil]]
//> shapeless.HNil
//>非常有趣,为什么它编译和工作不正确?因为我认为这是行不通的,导致对象无法以这种方式取得类型参数...

使用折叠。首先,我们需要一个多态函数,如果它具有所需的类型( String => A ),则可以将每个项目添加到累加器。对于某些
$ b $ pre $ $ $ $ c $ trait忽略延伸Poly2 {
implicit def default [A code $ c)),否则忽略它:

,L <:HList] = at [A,L]((_,l)=> 1)
}

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 )等等,这样做会是如果你想要得到无形体验的好处,那么很好的练习,但是 foldRight 要简单得多。

b
$ b

更新:实际上,对于它的价值,用 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 版本更加明显,但是这个也很漂亮。



< hr>

回应你的评论:你可以让解决方案更通用一些:

 < code $> 

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

object grabStringFunc extends grabFuncFrom [String]
$ b $ val filtered = hflist flatMap grabStringFunc

但是您仍然需要最后一步创建更高级别的函数作为对象(请参阅这个答案和迈尔斯的评论有关这个问题的一些讨论)。


It is easy to filter HList in shapeless by type:

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

But how can I make my custom type filter? I want smth like that: for example I got list of some functions:

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

So after usage of this filter, list of functions from type String to some other type will be constructed.

I had an idea to use map for this, but it was not successfull.

EDITION

More information about my comment:

I tried to test this ideas in map:

So if i got some lists (lets operate with 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

Very interesting, why it compiles and works incorrect? As I think it is not works, cause object cant take type prameters in such a way...

解决方案

The easiest way is to use a fold. First we need a polymorphic function that will add each item to the accumulator if it has the desired type (String => A for some A), and ignore it otherwise:

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](_ :: _)
}

Now the following will give the result you want in both 1.2.4 and 2.0.0-M1:

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

You could also write your own type class on the model of Filter, FilterAux (or Filter.Aux), etc.—and doing so would be a good exercise if you're trying to get the hang of Shapeless—but foldRight is a lot simpler.


Update: actually, for what it's worth, there's a slightly more concise way to do this with 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

I personally find the foldRight version a little more obvious, but this one's also pretty elegant.


In response to your comment: you can make the solution a little more generic like this:

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

But you're still going to need that last step where you create the higher rank function as an object (see e.g. this answer and Miles's comment there for some discussion of this issue).

这篇关于在不成形的过滤器中使用Scala的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆