Во-первых, обратите внимание, что (2) написано в так называемом стиле без точек, без третьего аргумента foldr.
https://en.wikipedia.org/wiki/Tacit_programming#Functional_programming
Кроме того, символ подчеркивания в \_ x -> x + 1
— это подстановочный знак, который просто отмечает место параметра, но не дает ему имени (подстановочный знак работает как безымянный параметр).
Во-вторых, (2) на самом деле не что иное, как простая рекурсивная функция, которая складывается вправо. foldr — это компактный способ написания таких рекурсивных функций (в вашем случае length
):
foldr :: (a -> b -> b) -> b -> [a]
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
Если мы напишем
foldr f c ls
- ls — это список, по которому должна повторяться наша рекурсивная функция (a — это тип элементов).
- c — это результат в базовом случае (когда рекурсивная рекурсивная функция применяется к пустому списку).
- f computes the result in the general case (when the recursive function is applied on a non-empty list). f takes two arguments:
- The head of the list and
- результат рекурсивного вызова хвоста списка.
Итак, при заданных f и c foldr будет рекурсивно проходить по списку ls.
Первый пример На странице Википедии о стиле без точек приводится пример того, как мы можем вычислить сумму всех элементов в списке с помощью foldr:
Вместо того, чтобы писать
sum [] = 0
sum (x:xs) = x + sum xs
мы можем написать
sum = foldr (+) 0
Секция оператора (+) — это функция с двумя аргументами, которая добавляет свои аргументы. Выражение
sum [1,2,3,4]
вычисляется как
1 + (2 + (3 + (4)))
(отсюда и «складывание вправо»).
Пример: умножение всех элементов.
Вместо
prod [] = 1
prod (x:xs) = x * prod xs
мы можем написать
prod = foldr (*) 1
Пример. Удаление всех вхождений значения из списка.
Вместо
remove _ [] = []
remove v (x:xs) = if x==v then remove v xs else x:remove v xs
мы можем написать
remove v = foldr (\x r -> if x==v then r else x:r) []
Ваше дело, (2)
Теперь мы можем полностью понять, что
length = foldr (\ _ x -> x + 1) 0
на самом деле то же самое, что
length [] = 0
length (x:xs) = length xs + 1
то есть функция длины.
Надеюсь, этот рекурсивный просмотр папки помог вам понять код.
person
Håkan
schedule
06.08.2019
length
так же, как вы здесь. Понятия не имею, почему они написали этоfoldr (\_ x -> x+1) 0
(по крайней мере, должно бытьfoldl'
!). - person luqui   schedule 05.08.2019