¿Qué es la división y fusión de banana en la programación funcional?

22

Estos términos fueron mencionados en mi curso universitario. Google rápido me señaló algunos documentos de la universidad, pero estoy buscando una explicación simple.

Gaurav Abbi
fuente
@jozefg: Gracias por el enlace a tu publicación. Una pregunta al respecto. En la oración "Un álgebra en este sentido es un par de un objeto C, y un mapa FC → C.", ¿se supone realmente que C es un objeto, o más bien una categoría? En otras palabras, no estoy seguro de si F denota un functor en una categoría, y las álgebras F son las álgebras inducidas por ese functor, o si F es una flecha particular de un objeto sobre sí mismo.
Giorgio
Ces un objeto en alguna categoría (digamos CC), Fes un functor de CC -> CCmodo que se asigna de CCnuevo a sí mismo. Ahora F CC -> CCes solo una flecha normal en la categoría CC. Entonces, un Fálgebra es un objeto C : CCy una flecha F C -> CadentroCC
Daniel Gratzer

Respuestas:

4

Aunque ya se han proporcionado 2 respuestas, no creo que la "división del plátano" se haya explicado aquí todavía.

De hecho, se define en "Programación funcional con plátanos, lentes, sobres y alambre de púas, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991"; ese artículo es difícil de leer (para mí) debido al uso intensivo de Squiggol. Sin embargo, "Un tutorial sobre la universalidad y la expresividad de fold, Graham Hutton, 1999" contiene una definición que es más fácil de analizar:

Como un primer ejemplo simple del uso de fold para generar tuplas, considere la función sumlength que calcula la suma y la longitud de una lista de números:

sumlength :: [Int] → (Int,Int)
sumlength xs = (sum xs, length xs)

Mediante una combinación directa de las definiciones de las funciones suma y longitud usando fold dado anteriormente, la función sumlength se puede redefinir como una sola aplicación de fold que genera un par de números a partir de una lista de números:

sumlength = fold (λn (x, y) → (n + x, 1 + y)) (0, 0)

Esta definición es más eficiente que la definición original, porque solo hace un recorrido transversal sobre la lista de argumentos, en lugar de dos recorridos separados. Generalizando a partir de este ejemplo, cualquier par de aplicaciones de pliegue a la misma lista siempre se puede combinar para dar una sola aplicación de pliegue que genera un par, apelando a la llamada propiedad de pliegue 'banana split' (Meijer, 1992) . El extraño nombre de esta propiedad deriva del hecho de que el operador de plegado a veces se escribe usando corchetes (| |) que se asemejan a plátanos, y el operador de emparejamiento a veces se denomina división. ¡Por lo tanto, su combinación se puede denominar división de plátano!

Klaas van Schelven
fuente
19

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.

Daniel Gratzer
fuente
2
Vale la pena mencionar que los plátanos son (| |) paréntesis que el documento original utiliza para definir cata
jk.
7

Aunque jozefg proporcionó una respuesta, no estoy seguro de si respondió la pregunta. La "ley de fusión" se explica en el siguiente documento:

Un tutorial sobre la universalidad y la expresividad del pliegue, GRAHAM HUTTON, 1999

Básicamente dice que, bajo ciertas condiciones, puede combinar ("fusionar") la composición de una función y doblarla en un solo pliegue, así que básicamente

h · doblar gw = doblar fv

Las condiciones para esta igualdad son

hw = v
h (gxy) = fx (hy)

La "ley de división de banana" o "ley de división de banana" es del artículo

Programación funcional con plátanos, lentes, sobres y alambre de púas, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991

Lamentablemente, el artículo es muy difícil de descifrar, ya que utiliza el formalismo Bird-Meertens, por lo que no pude entenderlo. Según tengo entendido, la "ley de división del plátano" dice que si tienes 2 pliegues que operan con el mismo argumento, se pueden fusionar en un solo pliegue.

Jackie
fuente