Haskell функция высшего порядка для расчета длины - PullRequest
0 голосов
/ 15 февраля 2012

Я не могу понять, что здесь происходит? Кто-нибудь может объяснить этот код? Как эта функция рассчитывает длину?

callength = foldr (\_ n -> 1 + n) 0

Почему он использует лямбда, подчеркивание, пробел между подчеркиванием и n и ноль с правой стороны?

1 Ответ

18 голосов
/ 15 февраля 2012

(\_ n -> 1 + n) просто означает функцию, которая принимает два аргумента и возвращает на один больше, чем ее второй аргумент.Подчеркивание просто означает, что параметр игнорируется.Для сравнения, в качестве объявления верхнего уровня без использования шаблона подстановки (подчеркивание) эта функция будет выглядеть следующим образом:

foo x n = 1 + n

Теперь вот пример списка:

[1, 2, 3, 4]

На самом деле это всего лишь синтаксический сахар для:

1 : 2 : 3 : 4 : []

То, что делает foldr, рекурсивно заменяет каждый (:) на данную функцию, а [] - на аргумент после функции (* ноль ).Таким образом, foldr f z [1, 2, 3, 4] для любых f и z выглядит следующим образом:

f 1 (f 2 (f 3 (f 4 z)))

(Вот почему foldr (:) [] просто возвращает тот же список, который вы ему дали, - в конечном итоге он восстанавливает исходныйСтруктура списка.)

В этом случае, используя функцию foo и ноль 0, она выглядит следующим образом:

foo 1 (foo 2 (foo 3 (foo 4 0)))

Мы знаем, что foo игнорирует свой первый аргумент, ивозвращает на один больше, чем его второй аргумент.Так что это то же самое, что и

1 + (1 + (1 + (1 + 0)))

, что равно 4, длина списка.По сути, сгиб игнорирует каждый элемент списка и просто добавляет один к аккумулятору для каждого элемента, давая длину.0 используется для завершения всего процесса, и поскольку длина пустого списка равна 0.

Чтобы увидеть это более подробно, мы можем постепенно расширять каждый вызов:

foldr foo 0 (1 : 2 : 3 : 4 : [])
foo 1 (foldr foo 0 (2 : 3 : 4 : []))
1 + foldr foo 0 (2 : 3 : 4 : [])
1 + foo 2 (foldr foo 0 (3 : 4 : []))
1 + 1 + foldr foo 0 (3 : 4 : [])
1 + 1 + foo 3 (foldr foo 0 (4 : []))
1 + 1 + 1 + foldr foo 0 (4 : [])
1 + 1 + 1 + foo 4 (foldr foo 0 [])
1 + 1 + 1 + 1 + foldr foo 0 []
1 + 1 + 1 + 1 + 0
1 + 1 + 1 + 1
1 + 1 + 2
1 + 3
4
...