Реализация последнего с помощью foldr1

У меня проблема с реализацией последней функции с помощью foldr1. Я предполагаю, что он берет самый правый элемент и обрабатывает его как значение аккумулятора, а затем применяет двоичную функцию к аккумулятору и его соседу, пока не достигнет начала данного списка. Однако приведенный ниже код не работает. Может ли кто-нибудь сказать мне, что с ним не так? Вместо того, чтобы возвращать последний элемент, он выводит первый.

last' list = foldr1 (\acc _ -> acc) list

person mcjkwlczk    schedule 20.06.2014    source источник
comment
Вам нужно вернуть второй аргумент, а не первый.   -  person Lee    schedule 21.06.2014
comment
но почему? я использую foldr1, а не foldl1   -  person mcjkwlczk    schedule 21.06.2014
comment
второй элемент это накопленное значение - меняется порядок обхода и порядок изменения параметров тоже...   -  person underrun    schedule 21.06.2014
comment
о, большое спасибо   -  person mcjkwlczk    schedule 21.06.2014


Ответы (1)


foldr :: (a -> b -> b) -> b -> [a] -> b

Как видите, foldr делает аккумулятор вторым аргументом, а значение из списка — первым. foldr1 ведет себя так же. Итак, как сказал Ли, вам нужно, чтобы ваша лямбда возвращала второй аргумент, а не первый. В качестве альтернативы вы можете сказать foldr1 (flip const)

person genisage    schedule 20.06.2014
comment
flip const не seq, было бы очень странно принудительно использовать элементы только для того, чтобы получить последний. - person Daniel Gratzer; 21.06.2014
comment
Однако foldr1 seq и foldr1 (\_ acc -> acc) имеют разную семантику. Все переходники в списке будут принудительно задействованы, если вы используете foldr1 seq, но это не относится к foldr1 (\_ acc -> acc). Это может быть важным отличием, если для оценки каждого элемента списка требуется очень много времени. Кроме того, если в xs есть какие-либо нижние значения, то foldr1 seq xs также является нижним (что может быть плохо). - person David Young; 21.06.2014