Así que esto es en realidad una referencia a un artículo de Meijer y algunos otros llamado " Programación funcional con plátanos, lentes, sobres y alambre de púas ", la idea básica es que podemos tomar cualquier tipo de datos recursivos, como por ejemplo
data List = Cons Int List | Nil
y podemos factorizar la recursividad en una variable de tipo
data ListF a = Cons Int a | Nil
¡La razón por la que agregué eso Fes porque ahora es un functor! También nos permite imitar listas, pero con un giro: para construir listas tenemos que anidar el tipo de lista
type ThreeList = ListF (ListF (ListF Void)))
Para recuperar nuestra lista original necesitamos seguir anidando esto infinitamente . Eso nos dará un tipo ListFFdonde
ListF ListFF == ListFF
Para hacer esto, defina un "tipo de punto fijo"
data Fix f = Fix {unfix :: f (Fix f)}
type ListFF = Fix ListF
Como ejercicio, debe verificar que esto satisfaga nuestra ecuación anterior. ¡Ahora finalmente podemos definir qué son los plátanos (catamorfismos)!
type ListAlg a = ListF a -> a
ListAlgs son el tipo de "lista de álgebras", y podemos definir una función particular
cata :: ListAlg a -> ListFF -> a
cata f = f . fmap (cata f) . unfix
Además
cata :: ListAlg a -> ListFF -> a
cata :: (Either () (Int, a) -> a) -> ListFF -> a
cata :: (() -> a) -> ((Int, a) -> a) -> ListFF -> a
cata :: a -> (Int -> a -> a) -> ListFF -> a
cata :: (Int -> a -> a) -> a -> [Int] -> a
¿Parecer familiar? cataes exactamente lo mismo que los pliegues derechos!
Lo que es realmente interesante es que podemos hacer esto en más que solo listas, cualquier tipo que se define con este "punto fijo de un functor" tiene un catay para acomodarlos a todos, solo tenemos que relajar la firma de tipo
cata :: (f a -> a) -> Fix f -> a
Esto en realidad está inspirado en una parte de la teoría de la categoría sobre la que escribí , pero esta es la carne del lado de Haskell.