Jadi ini sebenarnya direferensikan ke makalah oleh Meijer dan beberapa orang lain yang disebut " Pemrograman Fungsional dengan Pisang, Lensa, Amplop dan Kawat Berduri ", ide dasarnya adalah bahwa kita dapat mengambil tipe data rekursif, seperti
data List = Cons Int List | Nil
dan kita bisa memfaktorkan rekursi menjadi variabel tipe
data ListF a = Cons Int a | Nil
alasan mengapa saya menambahkan itu F
karena ini sekarang adalah functor! Itu juga memungkinkan kita untuk meniru daftar, tetapi dengan twist: untuk membangun daftar kita harus bersarang tipe daftar
type ThreeList = ListF (ListF (ListF Void)))
Untuk memulihkan daftar asli kita, kita perlu terus bersarang tanpa batas . Itu akan memberi kita jenis di ListFF
mana
ListF ListFF == ListFF
Untuk melakukan ini, tentukan "tipe titik tetap"
data Fix f = Fix {unfix :: f (Fix f)}
type ListFF = Fix ListF
Sebagai latihan, Anda harus memverifikasi ini memenuhi persamaan kami di atas. Sekarang kami akhirnya dapat menentukan apa pisang (katamorfisme)!
type ListAlg a = ListF a -> a
ListAlg
s adalah jenis "list algebras", dan kita dapat mendefinisikan fungsi tertentu
cata :: ListAlg a -> ListFF -> a
cata f = f . fmap (cata f) . unfix
Lebih jauh lagi
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
Terlihat familier? cata
persis sama dengan lipatan kanan!
Yang benar-benar menarik adalah bahwa kita dapat melakukan ini lebih dari sekadar daftar, jenis apa pun yang didefinisikan dengan "titik tetap dari functor" ini memiliki cata
dan untuk memperbarui mereka semua kita hanya perlu bersantai dengan tanda tangan jenis
cata :: (f a -> a) -> Fix f -> a
Ini sebenarnya diilhami dari sepotong teori kategori yang saya tulis , tetapi ini adalah daging dari sisi Haskell.