Рекурсия и итерация.

Apr 25, 2007 17:05

Похоже, что спор в моей голове о том, может ли любой рекурсивный алгоритм быть преобразован в итеративный (циклический), у меня разрешился. Кажется точку ставит следующие отношение, которое я нашел здесь:

foldl f v xs = foldr (λx g →(λa → g (f a x))) id xs v
Давайте рассмотрим подробнее определения функций foldl и foldr.

foldr f v [] = v
foldr f v (x: xs) = f x (foldr f v xs)

foldl f v [] = v
foldl f v (x: xs) = foldl f (f v x) xs(или, для наглядности посмотрим на картинки правой и левой свертки)

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

foldr f v [1, 2, 3, 4, 5] = f 1 (f 2 (f 3 (f 4 (f 5 v)))),
то для foldl этого не нужно

foldl f v [1, 2, 3, 4, 5] = f (f (f (f (f v 1) 2) 3) 4) 5
foldl аккумулирует выходной результат во втором аргументе, и ее можно реализовать при помощи цикла.

Что же нам дает найденное равенство? А то, что foldr всегда можно преобразовать в foldl. Однако обратное преобразование выполняется не всегда. Именно поэтому циклический алгоритм всегда можно преобразовать в рекурсивный, но рекурсивный не всегда. Рекурсивный алгоритм равен циклическому только тогда, когда это равенство выполняется и в ту и в другую сторону...

Это значит, что не все рекурсивные алгоритмы могут быть оптимизированы в циклические, без явной эмуляции структуры так или иначе выполняющей функцию стека.

Хочется верить, что разработка алгоритмов, атоматически преобразующих правую свертку в левую, или доказывающих невозможность этого, является делом времени, хотя конечно катаморфизмы[WIKI] foldl и foldr существуют не только для структур данных типа список. А универсальных операторов свертки, я пока еще не находил. Вероятнее всего, если такие алгоритмы и будут, они будут строго привязаны к типу данных.

haskell, catamorphism, fp

Previous post Next post
Up