1

我有下一个代码

val listOption: List[Option[Int]] = List(1.some, none, 2.some)

我想折叠元素,我写下一个代码

val result = listx.fold(0.some)((acc, el) => {
  (acc, el) match {
    case (Some(a), Some(b)) => Some(a + b)
    case (Some(a), _) => Some(a)
    case (_, Some(b)) => Some(b)
    case _ => el
  }
})
println(result.getOrElse(0)) // => 3 

这很好用,但我在 scalaz 来源中看到了下一个 tric

val composeFold = Foldable[List] compose Foldable[Option]
composeFold.fold(listOption) // => 3

但我不明白它是如何正确工作的,为什么 scalaz 不将此方法混合到实例中,以及 scala和 scalazlistOption之间有什么区别foldfold

4

1 回答 1

5

scalazfold函数使用Monoid元素的实例,因此您不必提供起始值和函数来组合元素。

AMonoid有两个函数zero/emptyappend/ combine。这Int可能是:

val intMonoid = new Monoid[Int] {
  def zero = 0
  def append(a: Int, b: => Int) = a + b
}

使用它Monoid[Int],我们可以将 Scalaz 编写fold为 Scala fold

import scalaz.Foldable
import scalaz.std.list._
import scalaz.std.anyVal._

val numbers = List(1,2,3)
Foldable[List].fold(numbers)                          // 6
// analogous to the following Scala fold
numbers.fold(intMonoid.zero)(intMonoid.append(_,_))   // 6

我们可以像你展示的那样结合Foldable[List]and :Foldable[Option]

import scalaz.std.option._
Foldable[List].fold(List(1,2))    // 3

Foldable[Option].fold(1.some)     // 1
Foldable[Option].fold(none[Int])  // 0

val foldListO = Foldable[List] compose Foldable[Option]
foldListO.fold(List(1.some, none, 2.some))  // 3

您可以使用foldable语法 import 和 use concatenateor suml/ sumr(也有但它与andfold冲突):List.foldOption.fold

import scalaz.syntax.foldable._
List(1,2,3).concatenate  // 6
1.some.concatenate       // 1

List(1.some, none, 2.some).concatenate.concatenate  // 3

除了像scalaz.std.list._and这样的特定导入scalaz.syntax.foldable._,您还可以使用 uber 导入 with import scalaz._, Scalaz._

于 2016-05-28T16:38:56.523 回答