Today we'll talk about quite complicated topic – recursion schemes. Hold tight, as the ride won't be easy.
First of all, I would like to stress that I'm still grokking this topic, so if you spot a mistake, please ping me back!
- catamorphism tears down a structure layer by layer – you may think of it as a general `fold` operation;
- anamorphism builds up a (recursive) structure layer by layer – you probably know it under `unfold` name;
Let's solve a problem: given a desired amount N, and an infinite supply S = { S1, S2, .. , Sm} of coins, how many ways can we make the change?
histo :: Functor f => CVAlgebra f a -> Fix f -> a,
where
CVAlgebra f a = f (Cofree f a) -> a - a course-of-value algebra,
Cofree f a = Cofree { attribute :: a, hole :: f (Cofree f a) } - cofree comonad
and
Fix f = f (Fix f) - fixpoint of functor f
Course-of-value algebra allows us to access the additional payload (attribute) of current recursive term, as well as fall deeper into it's hole.
type Fix t = t (t (t (t (t ...))))
For example, a singly-linked list can be described like so:
type List a = Fix (L a)
data L a b = Nil | Cons a b