4

Я пытаюсь изучить функциональное программирование и Scala, поэтому я читаю «Функциональное программирование в Scala» от Chiusano и Bjarnason. У меня возникли проблемы с пониманием того, что складывается влево и сбрасывать правильные методы в случае списка. Я осмотрелся здесь, но я не нашел что-то новичка. Таким образом, код, предоставляемый книги:Scala fold right и fold left

def foldRight[A,B](as: List[A], z: B)(f: (A, B) => B): B = as match { 
    case Nil => z 
    case Cons(h, t) => f(h, foldRight(t, z)(f)) 
} 

def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match { 
    case Nil => z 
    case Cons(h,t) => foldLeft(t, f(z,h))(f) 
} 

Где Cons и Nil являются:

case class Cons[+A](head: A, tail: List[A]) extends List[A] 
case object Nil extends List[Nothing] 

Так что же на самом деле складка левый и правый делать? Почему нужны «полезные» методы? Есть много других методов, которые используют их, и мне также сложно понять их, так как я не получаю этих двух.

+0

Посмотрите на следующую тему. http://stackoverflow.com/questions/24370549/foldleft-v-foldright-does-it-matter имеется много информации об этих операциях. Похож на дубликат для меня. – Pavel

+0

В этом вопросе кажется, что пользователь спрашивает, имеет ли хорошее понимание этого вопроса, я не знаю, с чем мне нужна помощь. – jrsall92

+2

Для кода, который вы предоставили. У вас есть какой-то конкретный вопрос? Что именно создает трудности? синтаксис? Ключом к пониманию разницы является способ рекурсивного вызова, сделанный для себя в обоих случаях. Это другое. Читайте о рекурсии хвоста. Надеюсь, это поможет. Дополнительные ссылки: https://oldfashionedsoftware.com/2009/07/10/scala-code-review-foldleft-and-foldright/ – Pavel

ответ

7

Согласно моему опыту, один из лучших способов тренировки интуиции, чтобы увидеть, как это работает на очень простых примерах:

List(1, 3, 8).foldLeft(100)(_ - _) == ((100 - 1) - 3) - 8 == 88 
List(1, 3, 8).foldRight(100)(_ - _) == 1 - (3 - (8 - 100)) == -94 

Как вы можете видеть, foldLeft/Right просто передает элемент списка и результат предыдущей заявки на операцию во вторых круглых скобках. Следует также упомянуть, что если вы примените эти методы к одному и тому же списку, они возвратят равные результаты, только если прикладная операция ассоциативна.

+0

Я думаю, вы хотели, чтобы ваша операция была «(_ - _)», то есть минусом вместо плюса. В противном случае очень хорошее объяснение различий между foldLeft и foldRight. – melston

1

Скажите, что у вас есть список номеров, и вы хотите добавить их все. Как бы Вы это сделали? Вы добавляете первый и второй, затем берете результат, добавляете это к третьему, берете результат этого, добавляете его к четвертому .. и так далее.

Это то, что вам нужно сделать.

List(1,2,3,4,5).foldLeft(0)(_ + _) 

Знак «+» является функцией, которую вы хотите применить, с первым операндом является результатом его применения к элементам до сих пор, а второй операнда является следующим элементом. Поскольку у вас нет «результата до сих пор» для первого приложения, вы указываете начальное значение - в этом случае 0, так как оно является элементом идентификации для добавления.

Допустим, вы хотите, чтобы умножить все список ваших элементов, со складкой, что бы

List(1,2,3,4,5).foldLeft(1)(_ * _) 

Fold имеет собственный Wikipedia page вы можете проверить.

Конечно, есть также записи ScalaDoc для foldLeft и foldRight.

Смежные вопросы