Примитивная рекурсия напрямую соответствует параморфизму.
Вы правы, что катаморфизм имеет эквивалентную теоретическую мощность параморфизму, но они могут отличаться во многих важных аспектах с операционной точки зрения. Например, давайте go в списки вместо Nats.
cata :: b -> (a -> b -> b) -> [a] -> b
cata = flip foldr -- I'm lazy, but this argument order makes a bit more sense for this example
para :: b -> (a -> [a] -> b -> b) -> [a] -> b
para z _ [] = z
para z f (x:xs) = f x xs (para z f xs)
-- Removes the first element from the list which is equal to the other argument
delete1 :: Eq a => a -> [a] -> [a]
delete1 x xs = cata (const []) (\el k found -> if not found && el == x then k True else el : k found) xs False
-- Removes the first element from the list which is equal to the other argument
delete2 :: Eq a => a -> [a] -> [a]
delete2 x xs = para [] (\el raw processed -> if el == x then raw else el : processed) xs
Посмотрите, насколько неудобно delete1
по сравнению с delete2
. Вы не только должны исказить лог c, превратив результат cata
в функцию, но и получите очень реальные эксплуатационные расходы. Вы должны пройти все в списке после нахождения подходящего элемента и заново создать все конструкторы (:)
. Это может иметь заметные затраты на эффективность. Для сравнения, delete2
, когда он находит целевой элемент, может просто использовать существующий конец списка для остатка, даже не глядя на него. Конечно, в большинстве случаев использования foldr
(в реальном мире, а не в этом примере) не создается функция и не требуется доступ к необработанному концу списка. Для них катаморфизм будет немного более эффективным просто из-за передачи меньшего количества данных.
Так что с точки зрения теоретической мощности они эквивалентны. С практической точки зрения каждый из них имеет свое применение, хотя катаморфизмы встречаются гораздо чаще.
Для некоторого расширения идеи в более общих терминах см. Библиотеку рекурсивных схем . Он использует довольно иную формулировку идеи, так что он может абстрагироваться от типов данных с разными формами, вместо того, чтобы нуждаться в другом типе для cata
/ para
для каждого типа данных, к которому они могут применяться. Но на самом деле это просто альтернативный способ объединения тех же идей, и другие виды морфизмов также охватываются, в том числе больше ниша (или даже возможно бесполезно ) ед.