Когда функция сворачивания, заданная для foldr
, принимает более двух параметров, часто это действительно скрытый foldl
.Давайте посмотрим, правда ли это здесь.
mystery a b c xs = foldr (\x rec a b -> rec x (b + c)) (\a b -> a + b - c) xs a b
Вывод двух «дополнительных» аргументов для функции свертывания:
mystery a b c xs = foldr (\x rec (a,b) -> rec (x,b + c)) (\(a,b) -> a + b - c) xs (a,b)
Извлечение функции f
из функции свертывания и finalStep
из нулевого случая:
mystery a b c xs = foldr (\x rec z -> rec (f z x)) finalStep xs (a,b)
where
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Заменить foldr
явной рекурсией:
mystery a b c xs = go xs (a,b)
where
go [] = finalStep
go (x:xs) = \z -> go xs (f z x)
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Переместить вызов на finalStep
вне go
:
mystery a b c xs = finalStep $ go xs (a,b)
where
go [] = id
go (x:xs) = \z -> go xs (f z x)
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Эта-расширение go
и обратный порядок аргументов:
mystery a b c xs = finalStep $ go (a,b) xs
where
go z [] = z
go z (x:xs) = go (f z x) xs
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Теперь go
- это в точности определение foldl f
, поэтому замените его следующим:
mystery a b c xs = finalStep $ foldl f (a,b) xs
where
f (a,b) x = (x,b + c)
finalStep (a,b) = a + b - c
Теперь у нас есть очень простая операция сгиба, которую можно легко выполнить.Основным выводом из вышесказанного является тот факт, что foldr (\x rec -> rec . f x) finalStep xs z
и finalStep $ foldl (flip f) z xs
одинаковы для любых f
, z
и xs
.