В компьютерном программировании анаморфизм - это функция, которая генерирует последовательность путем повторного применения функции к ее предыдущему результату. Вы начинаете с некоторого значения A и применяете к нему функцию f, чтобы получить B. Затем вы применяете f к B, чтобы получить C, и так далее, пока не будет достигнуто какое-то условие завершения. Анаморфизм - это функция, которая генерирует список A, B, C и т. Д. Вы можете думать об анаморфизме как разворачивание начального значения в последовательность.
Описание Вышеуказанной непрофессионала может быть сформулировано более формально в теории категории : анаморфизм из coinductive типа означает присвоение коалгебры своего уникальному морфизма к окончательной коалгебре из в endofunctor . Эти объекты используются в функциональном программировании как развороты .
Категоричны двойное (ака противоположности) от анаморфизма является катаморфизмом .
Анаморфизмы в функциональном программировании
В функциональном программировании , анаморфизм является обобщением понятия разверток на coinductive списков . Формально анаморфизмы - это общие функции, которые могут коркурсивно конструировать результат определенного типа и который параметризуется функциями, которые определяют следующий отдельный шаг конструирования.
Рассматриваемый тип данных определяется как наибольшая фиксированная точка ν X. FX функтора F . По универсальному свойству финальных коалгебр существует единственный морфизм коалгебр A → ν X. FX для любой другой F -коалгебры a: A → FA . Таким образом, можно определить функции от типа A _into_ в coinductive типа данных, определяя структуру коалгебры А на А .
Пример: потенциально бесконечные списки
В качестве примера тип потенциально бесконечных списков (с элементами фиксированного значения типа ) задается как фиксированная точка [значение] = ν X. значение × X + 1 , т.е. список состоит либо из значения и дополнительного списка, либо он пуст. Определение (псевдо) Haskell может выглядеть так:
данные [ значение ] = ( значение : [ значение ]) | []
Это неподвижная точка функтора F value
, где:
данные Может быть = Just | Ничего не данные F значение x = Может быть ( значение , x )
Легко проверить, что тип действительно [value]
изоморфен F value [value]
и, следовательно, [value]
является неподвижной точкой. (Также обратите внимание, что в Haskell наименьшая и наибольшая фиксированные точки функторов совпадают, поэтому индуктивные списки аналогичны коиндуктивным потенциально бесконечным спискам.)
Анаморфизм для списков (то , как правило , известны как разворачиваться ) будет строить (потенциально бесконечный) список из государственного значения. Обычно развертывание принимает значение состояния x
и функцию, f
которая возвращает либо пару значения и нового состояния, либо одноэлемент, чтобы отметить конец списка. Затем анаморфизм начнется с первого начального числа, вычислит, продолжается ли список или заканчивается, а в случае непустого списка, добавит вычисленное значение к рекурсивному вызову анаморфизма.
Определение разворачивания или анаморфизма для списков в Haskell ana
выглядит следующим образом:
ana :: ( state -> Maybe ( value , state )) -> state -> [ value ] ana f stateOld = case f stateOld of Nothing -> [] Just ( value , stateNew ) -> value : ana f stateNew
Теперь мы можем реализовать довольно общие функции с помощью ana , например, обратный отсчет:
f :: Int -> Maybe ( Int , Int ) f current = let oneSmaller = current - 1 in if oneSmaller < 0 then Nothing else Just ( oneSmaller , oneSmaller )
Эта функция будет уменьшать целое число и одновременно выводить его, пока оно не станет отрицательным, после чего отметит конец списка. Соответственно ana f 3
будет вычислять список [2,1,0]
.
Анаморфизмы в других структурах данных
Анаморфизм может быть определен для любого рекурсивного типа в соответствии с общим шаблоном, обобщающим вторую версию ana для списков.
Например, развертка для древовидной структуры данных
дерево данных a = Leaf a | Ветвь ( Дерево a ) a ( Дерево a )
составляет
ana :: ( b -> Either a ( b , a , b )) -> b -> Tree a ana unpool x = case unpool x of Left a -> Leaf a Right ( l , x , r ) -> Branch ( ана откручивать л ) х ( ана развинчивать г )
Чтобы лучше увидеть взаимосвязь между рекурсивным типом и его анаморфизмом, обратите внимание, что Tree
и List
можно определить так:
newtype List a = List { unCons :: Maybe ( a , List a )} newtype Tree a = Tree { unNode :: Either a ( Tree a , a , Tree a ))}
Аналогия с ana
появляется при переименовании b
в его типе:
newtype List a = List { unCons :: Maybe ( a , List a )} anaList :: ( list_a -> Maybe ( a , list_a )) -> ( list_a -> List a ) newtype Tree a = Tree { unNode :: Either a ( Tree a , a , Tree a ))} anaTree :: ( tree_a -> Either a ( tree_a , a , tree_a )) -> ( tree_a -> Tree a )
С этими определениями аргумент конструктора типа имеет тот же тип, что и тип возвращаемого значения первого аргумента ana
, с заменой рекурсивных упоминаний типа на b
.
История
Одной из первых публикаций , чтобы ввести понятие анаморфизм в контексте программирования был документ Функциональное программирование с бананами, Объективы, конвертами и колючей проволоки , [1] с помощью Эрика Мейера и др. , который был в контексте языка программирования Squiggol .
Приложения
Функции вроде zip
и iterate
являются примерами анаморфизмов. zip
берет пару списков, скажем ['a', 'b', 'c'] и [1,2,3], и возвращает список пар [('a', 1), ('b', 2) , ('c', 3)]. Iterate
берет вещь x и функцию f от таких вещей к таким вещам и возвращает бесконечный список, полученный в результате повторного применения f, то есть list [x, (fx), (f (fx)), ( f (f (fx))), ...].
zip ( a : as ) ( b : bs ) = if ( as == [] ) || ( bs == [] ) - || означает "или", затем [( a , b )] else ( a , b ) : ( zip as bs ) итерация f x = x : ( итерация f ( f x ))
Чтобы доказать это, мы можем реализовать и то, и другое с помощью нашего универсального развертывания ana
, используя простую рекурсивную процедуру:
zip2 = ana unsp fin, где fin ( as , bs ) = ( as == [] ) || ( bs == [] ) unsp (( a : as ), ( b : bs )) = (( a , b ), ( as , bs )) iterate2 f = ana ( \ a -> ( a , f a )) ( \ x -> False )
В языке , как Haskell, даже абстрактные функции fold
, unfold
а ana
являются лишь определенными терминами, как мы уже видели из приведенных выше определений.
Анаморфизмы в теории категорий
В теории категорий , anamorphisms являются категоричным двойными из катаморфизма (и катаморфизм являются категоричным сопряженным anamorphisms).
Это означает следующее. Предположим, что ( A , fin ) - финальная F -коалгебра для некоторого эндофунктора F некоторой категории в себя. Таким образом, fin является морфизмом из A в FA , и, поскольку он считается окончательным, мы знаем, что всякий раз, когда ( X , f ) является другой F -коалгеброй (морфизм f из X в FX ), будет существовать единственный гомоморфизм h из ( X , f ) в ( A , fin ), то есть морфизм h из X в A такой, что fin . h = Fh . f . Тогда для каждого такого f обозначим через ana f однозначно заданный морфизм h .
Другими словами, у нас есть следующие определяющие отношения, учитывая некоторые фиксированные F , A и плавник, как указано выше:
Обозначение
Обозначение для ana f, которое можно найти в литературе:. Используемые брекеты известны как брекеты для линз , после чего анаморфизмы иногда называют линзами .
Смотрите также
- Морфизм
- Морфизмы F-алгебр
- От начальной алгебры к алгебре: катаморфизм
- За анаморфизмом следует катаморфизм: гиломорфизм
- Расширение идеи катаморфизмов: параморфизм
- Расширение идеи анаморфизмов: апоморфизм
Рекомендации
- ^ Мейер, Эрик ; Фоккинга, Маартен; Патерсон, Росс (1991). «Функциональное программирование с бананами, линзами, конвертами и колючей проволокой». CiteSeerX 10.1.1.41.125 . Цитировать журнал требует
|journal=
( помощь )