具有部分功能的可折叠"foldMap":折叠收集?



说,我有以下对象:

case class MyFancyObject(a: String, b: Int, c : Vector[String])

我需要的是得到一个包含与给定偏函数匹配的所有"c"的单个Vector[String]

例如:

val xs = Vector(
  MyFancyObject("test1",1,Vector("test1-1","test1-2","test1-3")),
  MyFancyObject("test2",2,Vector("test2-1","test2-2","test2-3")),
  MyFancyObject("test3",3,Vector("test3-1","test3-2","test3-3")),
  MyFancyObject("test4",4,Vector("test4-1","test4-2","test4-3"))
)
val partialFunction1 : PartialFunction[MyFancyObject,Vector[String]] = {
  case MyFancyObject(_,b,c) if b > 2 => c
}

我需要得到的是:Vector("test3-1","test3-2","test3-3","test4-1","test4-2","test4-3")

我通过以下方式解决了这个问题:

val res1 = xs.foldMap{
  case MyFancyObject(_,b,c) if b > 2 => c
  case _ => Vector.empty[String]
}

然而,这让我很好奇。我在这里所做的似乎是一件非常常见和自然的事情:对于可折叠集合的每个元素,尝试应用一个部分函数,如果失败,则默认为Monoidempty(在我的例子中Vector.empty(。我在库中搜索,但还没有找到任何这样做的东西,所以我最终在我的代码中添加了这个扩展方法:

  implicit class FoldableExt[F[_], A](foldable : F[A]) {
    def foldCollect[B](pF: PartialFunction[A, B])(implicit F : Foldable[F], B : Monoid[B]) : B = {
      F.foldMap(foldable)(pF.applyOrElse(_, (_ : A) => B.empty))
    }
  }

我的问题是:

有什么理由为什么这种方法已经

不可用?这不是一个足够通用且足够常见的场景,还是我错过了什么?

我认为如果你真的需要部分函数,你不希望它泄漏到外面,因为它不是很好用。如果你想重用你的partialFunction1,最好的办法是lift它,使其成为一个返回Option的总函数。然后,您可以在使用分部函数的同一位置提供默认大小写。方法如下:

val res2 = xs.foldMap(partialFunction1.lift).getOrElse(Vector.empty)

foldMap(partialFunction1.lift)返回Some(Vector(test3-1, test3-2, test3-3, test4-1, test4-2, test4-3)) 。这正是您在res1中拥有的,但包裹在Option中。

相关内容

  • 没有找到相关文章

最新更新