1

i have a next code

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

i want to fold elements, i write the next code

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 

this workds fine, but i see in scalaz sources the next tric

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

But i do not understand how it correct work, and why scalaz not mix this methods into listOption instance, and what differenct between scala fold and scalaz fold

lito
  • 989
  • 8
  • 21

1 Answers1

5

The scalaz fold function uses the Monoid instance of the elements, so you don't have to supply a start value and a function to combine the elements.

A Monoid has two functions zero/empty and append/combine. For Int this could be :

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

Using this Monoid[Int] we can write the Scalaz fold as a 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

We can combine the Foldable[List] and Foldable[Option] like you showed :

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

You can use the foldable syntax import and use concatenate or suml/sumr (There is also fold but it clashes with List.fold and 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

Instead of the specific imports like scalaz.std.list._ and scalaz.syntax.foldable._, you could also use the uber imports with import scalaz._, Scalaz._.

Peter Neyens
  • 9,770
  • 27
  • 33
  • `concatenate` from FoldableSyntax, but in sources i see FoldableSyntax have fold method: `final def fold(implicit A: Monoid[A]): A = F.fold(self)(A)` how i can call fold in foldable syntax instead of fold from scala? – lito May 28 '16 at 20:09