Sun 22 Jun 2008
Recursion Schemes: A Field Guide
Posted by Edward Kmett under Haskell , Category Theory , Mathematics , Recursion SchemesI talk an awful lot about different recursion schemes in this blog.
What I want to do for the next few posts is taxonomize a list of the general recursion schemes I have seen, cite the original references for them where available, and provide a concise implementation of each and try to motivate the connections between them. I'll likely go back through and add more information or post motivating examples for each as I work.
The following recursion schemes can be found in category-extras, along with variations on the underlying themes, so this should work as a punch-list. I'll update this post with links as I go.
| Folds | ||
|---|---|---|
| Scheme | Code | Description |
| catamorphism† | Cata | tears down a structure level by level |
| paramorphism*† | Para | tears down a structure with primitive recursion |
| zygomorphism*† | Zygo | tears down a structure with the aid of a helper function |
| histomorphism† | Histo | tears down a structure with the aid of the previous answers it has given. |
| prepromorphism*† | Prepro | tears down a structure after repeatedly transforming it |
| Unfolds | ||
| Scheme | Code | Description |
| anamorphism† | Ana | builds up a structure level by level |
| apomorphism*† | Apo | builds up a structure opting to return a single level or an entire branch at each point |
| futumorphism† | Futu | builds up a structure multiple levels at a time |
| postpromorphism*† | Postpro | builds up a structure and repeatedly transforms it |
| Refolds | ||
| Scheme | Code | Description |
| hylomorphism† | Hylo | builds up and tears down a virtual structure |
| chronomorphism† | Chrono | builds up a virtual structure with a futumorphism and tears it down with a histomorphism |
| synchromorphism | Synchro | a high level transformation between data structures using a third data structure to queue intermediate results |
| exomorphism | Exo | a high level transformation between data structures from a trialgebra to a bialgebra |
| metamorphism | Erwig | a hylomorphism expressed in terms of bialgebras |
| metamorphism | Gibbons | A fold followed by an unfold; change of representation |
| dynamorphism† | Dyna | builds up a virtual structure with an anamorphism and tears it down with a histomorphism |
| Elgot algebra | Elgot | builds up a structure and tears it down but may shortcircuit the process during construction |
| Elgot coalgebra | Elgot | builds up a structure and tears it down but may shortcircuit the process during deconstruction |
* This gives rise to a family of related recursion schemes, modeled in category-extras with distributive law combinators.
† The scheme can be generalized to accept one or more F-distributive (co)monads.
Haskell preliminaries
We'll need a few preliminary types.
First, we need to be able to take the fixed point of a functor. Since the least and greatest fixpoints of a functor coincide in Haskell, we just call this 'Fix' rather than Mu or Nu.
data FixF f = InF { outF :: f (FixF f) }
Second, we'll need to define F-algebras and F-coalgebras.
type Algebra f a = f a -> a type Coalgebra f a = a -> f a
Finally, we need a slight generalization of these. For a comonad W, an F-W-Algebra takes the form:
type GAlgebra f w a = f (w a) -> a
And similarly for a monad M, an F-M-coalgebra has the form:
type GCoalgebra f m a = a -> f (m a)
The intended use of GAlgebra and GCoalgebra is that you use them with F-distributive comonads and monads respectively in the sense of Uustalu, Vene and Pardo [1].
We can obtain all of these by importing from category-extras.
import Control.Functor.Fix import Control.Functor.Algebra
References
[1] T. Uustalu, V. Vene, A. Pardo. Recursion Schemes from Comonads. Nordic Journal of Computing 8(2001), 366-390.

June 22nd, 2008 at 11:58 pm
[…] Links [Haddock] [Source] [Field Guide] […]
June 22nd, 2008 at 11:59 pm
[…] Links [Haddock] [Source] [Field Guide] […]
June 23rd, 2008 at 9:34 am
I was delightfully and utterly confused by 99% of this post, not at any fault of yours, mind you. I can’t wait till I actually start understanding all this stuff, it looks awesome…
/joe
June 23rd, 2008 at 10:37 am
I am hoping that with the individual entries, this will flesh out into a useful reference.
June 25th, 2008 at 1:51 pm
Thanks! :) More of this!
June 25th, 2008 at 4:04 pm
Thanks for this great resource. I’ve been using Haskell to teach myself category theory for some time now and a unified reference makes it much simpler.
June 26th, 2008 at 8:41 am
So is this mainly just useful for learning category theory, or is it useful for Haskell programming generally? And if the latter, will we see explanations along the lines of sigfpe’s explanation of monads?
June 26th, 2008 at 10:30 am
Sam,
I actualy find that I use some of these quite a bit, in particular I find that catamorphisms and paramorphisms pop up pretty much all over the place when designing compiler passes, pretty printers, etc.
For example, Kevin Millikin used a catamorphism to fuse into the removal of unnecessary administrative redexes into Plotkin’s call-by-value and call-by-name continuation passing style transformations, yielding two different one-pass optimizing CPS transformation algorithms.
http://www.brics.dk/~kmilli/millikin-one-pass-cps.pdf
While I lack Dan’s eloquence when it comes to motivating material for the completely uninitiated, I’ll see what I can do to spin up an introductory article on the topic after I finish collecting the existing results for this survey.
July 3rd, 2008 at 7:55 am
At the moment there are only in-depth entries for catamorphisms and paramorphisms, but edwardk aims to explain all of them in some detail eventually. Give these love so he knows you appreciate his efforts, and give him constructive feedback on his presentation so that even more people can benefit from his work.
July 3rd, 2008 at 12:48 pm
This is an awesome idea.
July 3rd, 2008 at 12:56 pm
I ran into a pedagogical stumbling block when I realized I should probably go through anamorphism, apomorphism, then generalized anamorphism next to motivate examples in terms of monads instead of comonads to avoid scaring people off. I’ll resume the postings when I get back from MSFP.
Speaking of which, is anyone sure what the first reference was to anamorphisms?
July 3rd, 2008 at 8:06 pm
Just posting to offer some some more support for this. The *morphisms side of things has many large pedagogical stumbling blocks for the uninitiated, even for folks who already know all the basic category theory stuff and aren’t scared off by terms like “natural transformation” and “pull-back” (or “comonad” for that matter).
Regarding your own pedagogy, broadly speaking it would seem to make sense to alternate between the folds and their related unfolds and refolds, at least to start with. I’ve found the explicit examples really nice to go along with the official definitions (the lack of examples being one of the stumbling blocks in the literature, even if all the examples are old-hat).
July 4th, 2008 at 12:34 pm
[…] Links [Haddock] [Source] [Field Guide] […]
July 6th, 2008 at 7:18 pm
So, for the mere mortals, that are still struggling to understand Haskell, is there any chance, that you could accompany the implementation examples with a mainstream imperative-language implementation? For example in Python. I realise that some of the examples would probably look quite bastardised, but it would help immensely as a “studying guide”.
July 7th, 2008 at 5:50 pm
[…] I had originally planned to describe these in more detail here, but Edward Kmett (edwardk) has begun writing a Field Guide to all of these recursion schemes. His posts on each of the foomorphisms include both category theory and concrete examples, and are an excellent read. As you can see from the front page of his Field Guide, there are many, many more than the four described in the original paper. Implementations of all of these and much more are available in category-extras on Hackage. […]