# Ackermann function (Haskell)

### From LiteratePrograms

The **Ackermann function** or **Ackermann-Péter function** is defined recursively for non-negative integers *m* and *n* as follows:

- 0 \mbox{ and } n = 0 \\ A(m-1, A(m, n-1)) & \mbox{if } m > 0 \mbox{ and } n > 0. \end{cases}"/>

In the theory of computation, the Ackermann function is a simple example of a recursive function that is not primitively recursive. Note that this function grows very quickly -- even `A(4, 3)`

cannot be feasibly computed on ordinary computers.

The Ackermann function is ideal for representation in Haskell and an excellent
use of its **pattern matching** facility and specifically ** n+k pattern matching**.

The Ackermann function could also have been easily implemented in Haskell with *conditional code* or *guards*.

With pattern matching you create multiple definitions of a function and specify patterns for the arguments. Haskell will use its pattern matching facility to invoke the first definition that matches the pattern.

Haskell has extremely little Housekeeping code

<<ackermann.hs>>=moduleAckermannwhere

The case that bottoms out the recursion uses simple pattern matching to match the first argument to 0 and binds the second argument to the variable n

<<ackermann.hs>>=ackermann 0 n = n+1

The case that reduces the first argument with primitive recursion
uses what is called *n+k pattern matching*, in an *n+k pattern* match **n>= k**.
In this case the *n+k pattern* is m+1 therefore the first argument or *m* must be
greater than 1.

The case that uses multiple recursion also uses *n+k pattern matching*.
Therefore both the first and second argument must be greater than 1

<<ackermann.hs>>=ackermann(m+1)0 = ackermann m 1 ackermann(m+1)(n+1)= ackermann m(ackermann(m+1)n)

Finally a "catch all" definition that use the underscore, which are wildcards that don't even bother to bind the values. Note the pattern matching goes in order, so something like this should always be last. This is nice approach for eeking out every bit of efficiency because catching invalid negative arguments doesn't affect performance of algorithm with valid arguments. I suppose I could have spit out an error message, but I simply return 0.

<<ackermann.hs>>=ackermann _ _ = 0