2016-05-28 6 views
1

У меня есть следующий кодscalaz Складная Compose

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 

это workds хорошо, но я вижу в источниках scalaz следующий Tric

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

Но я не понимаю, как это исправить работу, и почему scalaz не смешивает эти методы с экземпляром listOption и какие differenct между Скале fold и scalaz fold

ответ

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 но столкновения с 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._, вы также можете использовать импорт Uber с import scalaz._, Scalaz._ ,

+0

'concatenate' из FoldableSyntax, но в источниках я вижу FoldableSyntax имеют метод fold:' final def fold (неявный A: Monoid [A]): ​​A = F.fold (self) (A) 'как я могу позвонить fold в складном синтаксисе вместо складки из scala? – lito