In
functional programming
In computer science, functional programming is a programming paradigm where programs are constructed by Function application, applying and Function composition (computer science), composing Function (computer science), functions. It is a declarat ...
, the concept of catamorphism (from the
Ancient Greek
Ancient Greek (, ; ) includes the forms of the Greek language used in ancient Greece and the classical antiquity, ancient world from around 1500 BC to 300 BC. It is often roughly divided into the following periods: Mycenaean Greek (), Greek ...
: "downwards" and "form, shape") denotes the unique
homomorphism
In algebra, a homomorphism is a morphism, structure-preserving map (mathematics), map between two algebraic structures of the same type (such as two group (mathematics), groups, two ring (mathematics), rings, or two vector spaces). The word ''homo ...
from an
initial algebra
In mathematics, an initial algebra is an initial object in the Category (mathematics), category of F-algebra, -algebras for a given endofunctor . This initiality provides a general framework for mathematical induction, induction and recursion.
...
into some other algebra.
Catamorphisms provide generalizations of ''
folds'' of
lists to arbitrary
algebraic data type
In computer programming, especially functional programming and type theory, an algebraic data type (ADT) is a kind of composite data type, i.e., a data type formed by combining other types.
Two common classes of algebraic types are product ty ...
s, which can be described as
initial algebra
In mathematics, an initial algebra is an initial object in the Category (mathematics), category of F-algebra, -algebras for a given endofunctor . This initiality provides a general framework for mathematical induction, induction and recursion.
...
s.
The dual concept is that of
anamorphism that generalize ''unfolds''. A
hylomorphism
Hylomorphism is a philosophical doctrine developed by the Ancient Greek philosopher Aristotle, which conceives every physical entity or being ('' ousia'') as a compound of matter (potency) and immaterial form (act), with the generic form as imm ...
is the composition of an anamorphism followed by a catamorphism.
Definition
Consider an
initial
In a written or published work, an initial is a letter at the beginning of a word, a chapter (books), chapter, or a paragraph that is larger than the rest of the text. The word is ultimately derived from the Latin ''initiālis'', which means '' ...
-algebra for some
endofunctor of some
category
Category, plural categories, may refer to:
General uses
*Classification, the general act of allocating things to classes/categories Philosophy
* Category of being
* ''Categories'' (Aristotle)
* Category (Kant)
* Categories (Peirce)
* Category ( ...
into itself. Here
is a
morphism
In mathematics, a morphism is a concept of category theory that generalizes structure-preserving maps such as homomorphism between algebraic structures, functions from a set to another set, and continuous functions between topological spaces. Al ...
from
to
. Since it is initial, we know that whenever
is another
-algebra, i.e. a morphism
from
to
, there is a unique
homomorphism
In algebra, a homomorphism is a morphism, structure-preserving map (mathematics), map between two algebraic structures of the same type (such as two group (mathematics), groups, two ring (mathematics), rings, or two vector spaces). The word ''homo ...
from
to
. By the definition of the category of
-algebra, this
corresponds to a morphism from
to
, conventionally also denoted
, such that
. In the context of
-algebra, the uniquely specified morphism from the initial object is denoted by
and hence characterized by the following relationship:
*
*
Terminology and history
Another notation found in the literature is
. The open brackets used are known as banana brackets, after which catamorphisms are sometimes referred to as ''bananas'', as mentioned in
Erik Meijer ''et al''.
One of the first publications to introduce the notion of a catamorphism in the context of programming was the paper “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”, by
Erik Meijer ''et al.'',
which was in the context of the
Squiggol formalism.
The general categorical definition was given by
Grant Malcolm.
Examples
We give a series of examples, and then a more global approach to catamorphisms, in the
Haskell
Haskell () is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research, and industrial applications, Haskell pioneered several programming language ...
programming language.
Catamorphism for Maybe-algebra
Consider the functor
Maybe
defined in the below Haskell code:
data Maybe a = Nothing , Just a -- Maybe type
class Functor f where -- class for functors
fmap :: (a -> b) -> (f a -> f b) -- action of functor on morphisms
instance Functor Maybe where -- turn Maybe into a functor
fmap g Nothing = Nothing
fmap g (Just x) = Just (g x)
The initial object of the Maybe-Algebra is the set of all objects of natural number type
Nat
together with the morphism
ini
defined below:
data Nat = Zero , Succ Nat -- natural number type
ini :: Maybe Nat -> Nat -- initial object of Maybe-algebra (with slight abuse of notation)
ini Nothing = Zero
ini (Just n) = Succ n
The
cata
map can be defined as follows:
[
cata :: (Maybe b -> b) -> (Nat -> b)
cata g Zero = g (fmap (cata g) Nothing) -- Notice: fmap (cata g) Nothing = g Nothing and Zero = ini(Nothing)
cata g (Succ n) = g (fmap (cata g) (Just n)) -- Notice: fmap (cata g) (Just n) = Just (cata g n) and Succ n = ini(Just n)
As an example consider the following morphism:
g :: Maybe String -> String
g Nothing = "go!"
g (Just str) = "wait..." ++ str
Then ]cata g ((Succ. Succ . Succ) Zero)
will evaluate to "wait... wait... wait... go!".
List fold
For a fixed type a
consider the functor MaybeProd a
defined by the following:
data MaybeProd a b = Nothing , Just (a, b) -- (a,b) is the product type of a and b
class Functor f where -- class for functors
fmap :: (a -> b) -> (f a -> f b) -- action of functor on morphisms
instance Functor (MaybeProd a) where -- turn MaybeProd a into a functor, the functoriality is only in the second type variable
fmap g Nothing = Nothing
fmap g (Just (x,y)) = Just (x, g y)
The initial algebra of MaybeProd a
is given by the lists of elements with type a
together with the morphism ini
defined below:
data List a = EmptyList , Cons a (List a)
ini :: MaybeProd a (List a) -> List a -- initial algebra of MaybeProd a
ini Nothing = EmptyList
ini (Just (n,l)) = Cons n l
The cata
map can be defined by:
cata :: (MaybeProd a b -> b) -> (List a -> b)
cata g EmptyList = g (fmap (cata g) Nothing) -- Note: ini Nothing = EmptyList
cata g (Cons s l) = g (fmap (cata g) (Just (s,l))) -- Note: Cons s l = ini (Just (s,l))
Notice also that cata g (Cons s l) = g (Just (s, cata g l))
.
As an example consider the following morphism:
g :: MaybeProd Int Int -> Int
g Nothing = 3
g (Just (x,y)) = x*y
cata g (Cons 10 EmptyList)
evaluates to 30. This can be seen by expanding
cata g (Cons 10 EmptyList) = g (Just (10,cata g EmptyList)) = 10*(cata g EmptyList) = 10*(g Nothing) = 10*3
.
In the same way it can be shown, that
cata g (Cons 10 (Cons 100 (Cons 1000 EmptyList)))
will evaluate to 10*(100*(1000*3)) = 3.000.000.
The cata
map is closely related to the right fold (see Fold (higher-order function)
In functional programming, fold (also termed reduce, accumulate, aggregate, compress, or inject) refers to a family of higher-order functions that analyze a recursive data structure and through use of a given combining operation, recombine the re ...
) of lists foldrList
.
The morphism lift
defined by
lift :: (a -> b -> b) -> b -> (MaybeProd a b -> b)
lift g b0 Nothing = b0
lift g b0 (Just (x,y)) = g x y
relates cata
to the right fold foldrList
of lists via:
foldrList :: (a -> b -> b) -> b-> List a -> b
foldrList fun b0 = cata (lift fun b0)
The definition of cata
implies, that foldrList
is the right fold and not the left fold.
As an example: foldrList (+) 1 (Cons 10 (Cons 100 (Cons 1000 EmptyList)))
will evaluate to 1111 and foldrList (*) 3 (Cons 10 (Cons 100 (Cons 1000 EmptyList))
to 3.000.000.
Tree fold
For a fixed type a
, consider the functor mapping types b
to a type that contains a copy of each term of a
as well as all pairs of b
's (terms of the product type of two instances of the type b
). An algebra consists of a function to b
, which either acts on an a
term or two b
terms. This merging of a pair can be encoded as two functions of type a -> b
resp. b -> b -> b
.
type TreeAlgebra a b = (a -> b, b -> b -> b) -- the "two cases" function is encoded as (f, g)
data Tree a = Leaf a , Branch (Tree a) (Tree a) -- which turns out to be the initial algebra
foldTree :: TreeAlgebra a b -> (Tree a -> b) -- catamorphisms map from (Tree a) to b
foldTree (f, g) (Leaf x) = f x
foldTree (f, g) (Branch left right) = g (foldTree (f, g) left) (foldTree (f, g) right)
treeDepth :: TreeAlgebra a Integer -- an f-algebra to numbers, which works for any input type
treeDepth = (const 1, \i j -> 1 + max i j)
treeSum :: (Num a) => TreeAlgebra a a -- an f-algebra, which works for any number type
treeSum = (id, (+))
General case
Deeper category theoretical studies of initial algebras reveal that the F-algebra obtained from applying the functor to its own initial algebra is isomorphic to it.
Strong type systems enable us to abstractly specify the initial algebra of a functor f
as its fixed point ''a = f a''. The recursively defined catamorphisms can now be coded in single line, where the case analysis (like in the different examples above) is encapsulated by the fmap. Since the domain of the latter are objects in the image of f
, the evaluation of the catamorphisms jumps back and forth between a
and f a
.
type Algebra f a = f a -> a -- the generic f-algebras
newtype Fix f = Iso -- gives us the initial algebra for the functor f
cata :: Functor f => Algebra f a -> (Fix f -> a) -- catamorphism from Fix f to a
cata alg = alg . fmap (cata alg) . invIso -- note that invIso and alg map in opposite directions
Now again the first example, but now via passing the Maybe functor to Fix. Repeated application of the Maybe functor generates a chain of types, which, however, can be united by the isomorphism from the fixed point theorem. We introduce the term zero
, which arises from Maybe's Nothing
and identify a successor function with repeated application of the Just
. This way the natural numbers arise.
type Nat = Fix Maybe
zero :: Nat
zero = Iso Nothing -- every 'Maybe a' has a term Nothing, and Iso maps it into a
successor :: Nat -> Nat
successor = Iso . Just -- Just maps a to 'Maybe a' and Iso maps back to a new term
pleaseWait :: Algebra Maybe String -- again the silly f-algebra example from above
pleaseWait (Just string) = "wait.. " ++ string
pleaseWait Nothing = "go!"
Again, the following will evaluate to "wait.. wait.. wait.. wait.. go!": cata pleaseWait (successor.successor.successor.successor $ zero)
And now again the tree example. For this we must provide the tree container data type so that we can set up the fmap
(we didn't have to do it for the Maybe
functor, as it's part of the standard prelude).
data Tcon a b = TconL a , TconR b b
instance Functor (Tcon a) where
fmap f (TconL x) = TconL x
fmap f (TconR y z) = TconR (f y) (f z)
type Tree a = Fix (Tcon a) -- the initial algebra
end :: a -> Tree a
end = Iso . TconL
meet :: Tree a -> Tree a -> Tree a
meet l r = Iso $ TconR l r
treeDepth :: Algebra (Tcon a) Integer -- again, the treeDepth f-algebra example
treeDepth (TconL x) = 1
treeDepth (TconR y z) = 1 + max y z
The following will evaluate to 4: cata treeDepth $ meet (end "X") (meet (meet (end "YXX") (end "YXY")) (end "YY"))
See also
*Morphism
In mathematics, a morphism is a concept of category theory that generalizes structure-preserving maps such as homomorphism between algebraic structures, functions from a set to another set, and continuous functions between topological spaces. Al ...
* Morphisms of F-algebras
** From a coalgebra to a final coalgebra: Anamorphism
** An anamorphism followed by an catamorphism: Hylomorphism
Hylomorphism is a philosophical doctrine developed by the Ancient Greek philosopher Aristotle, which conceives every physical entity or being ('' ousia'') as a compound of matter (potency) and immaterial form (act), with the generic form as imm ...
** Extension of the idea of catamorphisms: Paramorphism
** Extension of the idea of anamorphisms: Apomorphism
References
Further reading
*
{{refend
External links
Catamorphisms
at HaskellWiki
Catamorphisms
by Edward Kmett
* Catamorphisms in F# (Par
1
2
3
4
5
6
7
by Brian McNamara
Catamorphisms in Haskell
Category theory
Recursion schemes
Functional programming
Morphisms
Iteration in programming