Cos'è la banana split e la fusione nella programmazione funzionale?


22

Questi termini sono stati menzionati nel mio corso universitario. La rapida ricerca su google mi ha indicato alcuni documenti universitari, ma sto cercando una spiegazione semplice.


@jozefg: grazie per il link al tuo post. Una domanda al riguardo. Nella frase "Un'algebra in questo senso è una coppia di un oggetto C e una mappa FC → C.", C dovrebbe davvero essere un oggetto, o piuttosto una categoria? In altre parole, non sono sicuro che F indichi un funzione in una categoria e le algebre F sono le algebre indotte da quel funzione, se F è una freccia particolare da un oggetto su se stesso.
Giorgio,

Cè un oggetto in qualche categoria (diciamo CC), Fè un funzione da CC -> CCquindi si CCricollega a se stesso. Ora F CC -> CCè solo una normale freccia nella categoria CC. Quindi Fun'algebra è un oggetto C : CCe una freccia F C -> CdentroCC
Daniel Gratzer l'

Risposte:


4

Anche se sono già state fornite 2 risposte, non credo che la "banana split" sia stata ancora spiegata qui.

È infatti definito in "Programmazione funzionale con banane, lenti, buste e filo spinato, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991"; quell'articolo è difficile da leggere (per me) a causa del suo uso intenso di Squiggol. Tuttavia, "Un tutorial sull'universalità e l'espressività di fold, Graham Hutton, 1999" contiene una definizione che è più facile da analizzare:

Come semplice primo esempio dell'uso di fold per generare tuple, considera la funzione sumlength che calcola la somma e la lunghezza di un elenco di numeri:

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

Combinando in modo semplice le definizioni della somma delle funzioni e della lunghezza usando fold dato in precedenza, la funzione sumlength può essere ridefinita come una singola applicazione di fold che genera una coppia di numeri da un elenco di numeri:

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

Questa definizione è più efficiente della definizione originale, in quanto esegue solo un singolo attraversamento sull'elenco degli argomenti, anziché due attraversamenti separati. Generalizzando da questo esempio, qualsiasi coppia di applicazioni di fold nella stessa lista può sempre essere combinata per dare un'unica applicazione di fold che genera una coppia, facendo appello alla cosiddetta proprietà 'banana split' di fold (Meijer, 1992) . Lo strano nome di questa proprietà deriva dal fatto che l' operatore di piegatura è talvolta scritto usando parentesi (| |) che assomigliano a banane, e l'operatore di accoppiamento è talvolta chiamato split. Quindi, la loro combinazione può essere definita una banana split!


19

Quindi questo è in realtà un riferimento a un articolo di Meijer e alcuni altri chiamati " Programmazione funzionale con banane, obiettivi, buste e filo spinato ", l'idea di base è che possiamo prendere qualsiasi tipo di dati ricorsivo, come dire

 data List = Cons Int List | Nil

e possiamo fattorizzare la ricorsione in una variabile di tipo

 data ListF a = Cons Int a | Nil

il motivo per cui l'ho aggiunto Fè perché ora è un funzione! Ci consente anche di imitare gli elenchi, ma con una svolta: per creare elenchi dobbiamo nidificare il tipo di elenco

type ThreeList = ListF (ListF (ListF Void)))

Per recuperare la nostra lista originale dobbiamo continuare a nidificarla all'infinito . Questo ci darà un tipo ListFFdove

  ListF ListFF == ListFF

Per fare ciò, definire un "tipo a virgola fissa"

  data Fix f = Fix {unfix :: f (Fix f)}
  type ListFF = Fix ListF

Come esercizio, dovresti verificare che questo soddisfi la nostra equazione di cui sopra. Ora possiamo finalmente definire quali sono le banane (catamorfismi)!

  type ListAlg a = ListF a -> a

ListAlgs sono il tipo di "elenco algebre" e possiamo definire una particolare funzione

  cata :: ListAlg a -> ListFF -> a
  cata f = f . fmap (cata f) . unfix

Inoltre

  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

Ti sembra familiare? cataè esattamente lo stesso delle pieghe a destra!

La cosa veramente interessante è che possiamo farlo oltre a semplici elenchi, qualsiasi tipo definito con questo "punto fisso di un funzione" ha un catae per accontentarli tutto ciò che dobbiamo solo rilassare

  cata :: (f a -> a) -> Fix f -> a

Questo è in realtà ispirato da un pezzo di teoria delle categorie che ho scritto su , ma questa è la carne del lato Haskell.


2
vale la pena ricordare che le banane sono (| |) parentesi che il documento originale usa per definire cata
jk.

7

Sebbene jozefg abbia fornito una risposta, non sono sicuro che abbia risposto alla domanda. La "legge sulla fusione" è spiegata nel seguente documento:

Un tutorial sull'universalità e l'espressività di fold, GRAHAM HUTTON, 1999

Fondamentalmente dice che in alcune condizioni è possibile combinare ("fondere") la composizione di una funzione e piegare in una singola piega, quindi sostanzialmente

h · fold gw = fold fv

Le condizioni per questa uguaglianza sono

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

La "banana split" o "banana split law" proviene dall'articolo

Programmazione funzionale con banane, lenti, buste e filo spinato, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991

Sfortunatamente l'articolo è molto difficile da decifrare in quanto usa il formalismo di Bird-Meertens, quindi non sono riuscito a capirlo. Per quanto ho capito la "legge sulla divisione delle banane", dice che se hai 2 pieghe che operano sullo stesso argomento, possono essere unite in un'unica piega.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.