Разница между кратным и метод использовать-foldleft и foldRight?


примечание: Я нахожусь на Scala 2.8-может ли это быть проблемой?

почему я не могу использовать fold функция так же, как foldLeft или foldRight?

на установить scaladoc он говорит, что:

результатом сворачивания может быть только супертип параметра типа этой параллельной коллекции T.

но я не вижу параметра типа T в сигнатуре функции:

def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1

что такое разница между foldLeft-Right и fold, и как я могу использовать последний?

EDIT: например, как бы я написал складку, чтобы добавить все элементы в список? С foldLeft что будет:

val foo = List(1, 2, 3)
foo.foldLeft(0)(_ + _)

// now try fold:
foo.fold(0)(_ + _)
>:7: error: value fold is not a member of List[Int]
  foo.fold(0)(_ + _)
    ^
5 60

5 ответов:

вы правы о том, что старая версия Scala является проблемой. Если вы посмотрите на страница scaladoc для Scala 2.8.1 вы не увидите там сгиба (что согласуется с вашим сообщением об ошибке). Видимо,fold был представлен в Scala 2.9.

короткий ответ:

foldRight партнеры справа. То есть элементы будут накапливаться в порядке справа налево:

List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))

foldLeft соратников налево. Т. е. аккумулятор будет инициализирован и элементы будут добавлены к аккумулятору слева-направо:

List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c)

fold и ассоциативные в том, что порядок, в котором элементы добавляются вместе не определен. То есть аргументы к fold сформировать моноидом.

fold вопреки foldRight и foldLeft, не дает никаких гарантий относительно порядка, в котором будут обрабатываться элементы коллекции. Вы, вероятно, захотите использовать fold, с его более ограниченной сигнатурой, с параллельными коллекциями, где отсутствие гарантированного порядка обработки помогает параллельной коллекции реализовать сворачивание параллельным способом. Причина изменения подписи аналогична: с дополнительными ограничениями легче сделать параллель складывать.

для вашего конкретного примера вы бы закодировали его так же, как и с foldLeft.

val ns = List(1, 2, 3, 4)
val s0 = ns.foldLeft (0) (_+_) //10
val s1 = ns.fold (0) (_+_) //10
assert(s0 == s1)

согласен с другими ответами. подумайте о том, чтобы дать простой иллюстративный пример:

 object MyClass {
 def main(args: Array[String]) {
val numbers = List(5, 4, 8, 6, 2)
 val a =  numbers.fold(0) { (z, i) =>
 {
     println("fold val1 " + z +" val2 " + i)
  z + i

 }
}
println(a)
 val b =  numbers.foldLeft(0) { (z, i) =>
 println("foldleft val1 " + z +" val2 " + i)
  z + i

}
println(b)
   val c =  numbers.foldRight(0) { (z, i) =>
   println("fold right val1 " + z +" val2 " + i)
  z + i

}
println(c)
 }
}

результат говорит сам за себя :

fold val1 0 val2 5
fold val1 5 val2 4
fold val1 9 val2 8
fold val1 17 val2 6
fold val1 23 val2 2
25
foldleft val1 0 val2 5
foldleft val1 5 val2 4
foldleft val1 9 val2 8
foldleft val1 17 val2 6
foldleft val1 23 val2 2
25
fold right val1 2 val2 0
fold right val1 6 val2 2
fold right val1 8 val2 8
fold right val1 4 val2 16
fold right val1 5 val2 20
25