Изучай Haskell во имя добра! (Липовача) - страница 56

относится к этой функции. Так что пропуск скобок экономит на записи. Конечно, ничто не мешает использовать скобки, если это вам больше нравится.

Тем не менее есть случаи, когда использование такой нотации оправдано. Я думаю, что функция >flip будет лучше читаться, если мы объявим её так:

>flip' :: (a –> b –> c) –> b –> a –> c

>flip' f = \x y –> f y x

Несмотря на то что эта запись равнозначна >flip' f x y = f y x, мы даём понять, что данная функция чаще всего используется для создания новых функций. Самый распространённый сценарий использования >flip – вызов её с некоторой функцией и передача результирующей функции в >map или >zipWith:

>ghci> zipWith (flip (++)) ["люблю тебя", "любишь меня"] ["я ", "ты "]

>["я люблю тебя","ты любишь меня"]

>ghci> map (flip subtract 20) [1,2,3,4]

>[19,18,17,16]

Итак, используйте лямбда-выражения таким образом, когда хотите явно показать, что ваша функция должна быть частично применена и передана далее как параметр.

Я вас сверну!


Когда мы разбирались с рекурсией, то во всех функциях для работы со списками наблюдали одну и ту же картину. Базовым случаем, как правило, был пустой список. Мы пользовались образцом >(x:xs) и затем делали что-либо с «головой» и «хвостом» списка. Как выясняется, это очень распространённый шаблон. Были придуманы несколько полезных функций для его инкапсуляции. Такие функции называются свёртками (folds). Свёртки позволяют свести структуру данных (например, список) к одному значению.

Функция свёртки принимает бинарную функцию, начальное значение (мне нравится называть его «аккумулятором») и список. Бинарная функция принимает два параметра. Она вызывается с аккумулятором и первым (или последним) элементом из списка и вычисляет новое значение аккумулятора. Затем функция вызывается снова, с новым значением аккумулятора и следующим элементом из списка, и т. д. То, что остаётся в качестве значения аккумулятора после прохода по всему списку, и есть результат свёртки.

Левая свёртка foldl

Для начала рассмотрим функцию >foldl – свёртка слева. Она сворачивает список, начиная с левой стороны. Бинарная функция применяется для начального значения и первого элемента списка, затем для вновь вычисленного аккумулятора и второго элемента списка и т. д.

Снова реализуем функцию >sum, но на этот раз будем пользоваться свёрткой вместо явной рекурсии.



>sum' :: (Num a) => [a] –> a

>sum' xs = foldl (\acc x –> acc + x) 0 xs

Проверка – раз, два, три!

>ghci> sum' [3,5,2,1]

>11

Давайте посмотрим более внимательно, как работает функция >foldl. Бинарная функция – это лямбда-выражение