Bu aslında Yani bir "denilen Meijer ve birkaç başkaları tarafından bir kağıda başvurulan Muz, Lensler, Zarflar ve Dikenli telle Fonksiyonel Programlama ", temel fikir biz söz hakkından gibi herhangi özyinelemeli veri türünü alabilir olmasıdır
data List = Cons Int List | Nil
ve özyinelemeyi bir tür değişkenine ayırabiliriz
data ListF a = Cons Int a | Nil
Bunu eklememin sebebi bunun F
bir functor olduğudur. Ayrıca listeleri taklit etmemize de izin verir, ancak bir bükümle: listeleri oluşturmak için liste türünü yerleştirmeliyiz
type ThreeList = ListF (ListF (ListF Void)))
Orijinal listemizi kurtarmak için, bunu sonsuz bir şekilde yuvalamaya devam etmemiz gerekiyor . Bu bize bir tür verecektir ListFF
nerede
ListF ListFF == ListFF
Bunu yapmak için bir "sabit nokta tipi" tanımlayın
data Fix f = Fix {unfix :: f (Fix f)}
type ListFF = Fix ListF
Bir egzersiz olarak, bunun bizim yukarıdaki denklemimize uyduğunu doğrulamalısınız. Şimdi nihayetinde muzların (catamorfizmlerin) ne olduğunu tanımlayabiliriz!
type ListAlg a = ListF a -> a
ListAlg
s "list cebir" tipidir ve belirli bir işlevi tanımlayabiliriz
cata :: ListAlg a -> ListFF -> a
cata f = f . fmap (cata f) . unfix
Daha fazla
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
Tanıdık görünmek? cata
kesinlikle doğru kıvrımlarla aynıdır!
Asıl ilginç olan, bunu sadece listelerden daha fazlasını yapabilmemiz, bu "bir functorun sabit noktası" ile tanımlanmış herhangi bir türün sahip olması cata
ve bir tür imzaya gevşetmek için elimizden geleni yapmasıdır.
cata :: (f a -> a) -> Fix f -> a
Bu aslında hakkında yazdığım bir kategori kuramından ilham alıyor , ancak bu Haskell tarafının eti.