我有下一个代码
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来源中看到了下一个三元组
val composeFold = Foldable[List] compose Foldable[Option]
composeFold.fold(listOption) // => 3
但是我不明白它是如何正确的工作,以及为什么scalaz不将这些方法混合到listOption
实例中,以及scala fold
和scalaz fold
之间的区别
答案 0 :(得分:5)
scalaz fold
函数使用元素的Monoid
实例,因此您不必提供起始值和函数来组合元素。
Monoid
有两个函数zero
/ empty
和append
/ 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]
和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
语法导入并使用concatenate
或suml
/ sumr
(还有fold
但它与{{1}冲突}和List.fold
):
Option.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._
和scalaz.syntax.foldable._
等特定导入。