Mutating Norm Recursion
This page is part of a series on Arithmetic Made Difficult.
This post is literate Haskell; you can load the source into GHCi and play along.
{-# LANGUAGE NoImplicitPrelude #-}
module MutatingNormRecursion (
mnormrec
) where
import Testing
import Booleans
import DisjointUnions
import Unary
import NaturalNumbers
import MutatingRecursion
Just as mutating recursion generalizes bailout recursion at the expense of losing the tail recursive evaluation strategy, it will be handy to have a generalization of norm recursion that sacrifices tail recursion. We’ll call this mutating norm recursion.
Let \((A,\varepsilon,\varphi)\) be an inductive set, and let \(\eta : A \rightarrow \nats\) be an inductive norm. Now suppose we have mappings \(\delta : A \rightarrow B\) and \(\sigma : A \times B \rightarrow B\). Then there is a unique map \(\Theta : A \rightarrow B\) such that. \[\Theta(a) = \left\{\begin{array}{l} \delta(a) & \mathrm{if}\ \iszero(\eta(a)) \\ \sigma(a,\Theta(\varphi(a))) & \mathrm{otherwise} \end{array}\right.\] We denote this unique map by \(\mnormrec(\varphi)(\eta)(\delta)(\sigma)\).
We define maps \(\beta : \nats \times A \rightarrow \bool\) by \[\beta(n,a) = \iszero(\eta(a)),\] \(\psi : \nats \times A \rightarrow B\) by \[\psi(n,a) = \delta(a),\] \(\chi : \nats \times A \times B \rightarrow B\) by \[\chi(n,a,b) = \sigma(a,b),\] and \(\omega : \nats \times A \rightarrow A\) by \[\omega(n,a) = \varphi(a).\] Now we define \(\Omega : \nats \times A \rightarrow B\) by \[\Omega = \mutrec(\delta)(\beta)(\psi)(\chi)(\omega).\]
We first need the following intermediate result: for all \(a \in A\) and \(k \in \nats\), we claim that \[\Omega(\nplus(\eta(\varphi(a)),k),\varphi(a)) = \Omega(\eta(\varphi(a)),\varphi(a)).\] To see this, we proceed by strong induction on \(\eta(\varphi(a))\). For the base case, suppose \(\eta(\varphi(a)) = \zero\); we show the equality holds by induction on \(k\). For the base case \(k = \zero\), we have \[\begin{eqnarray*} & & \Omega(\nplus(\eta(\varphi(a)),k),\varphi(a)) \\ & = & \Omega(\nplus(\zero,\zero),\varphi(a)) \\ & \href{/posts/arithmetic-made-difficult/Plus.html#cor-plus-up-zero} = & \Omega(\zero,\varphi(a)) \\ & = & \Omega(\eta(\varphi(a)),\varphi(a)) \end{eqnarray*}\] as needed. For the inductive step, suppose the equality holds for some \(k\) when \(\eta(\varphi(a)) = \zero\). Now \[\begin{eqnarray*} & & \Omega(\nplus(\eta(\varphi(a)),\next(k)),\varphi(a)) \\ & \href{/posts/arithmetic-made-difficult/Plus.html#thm-plus-next-right} = & \Omega(\next(\nplus(\eta(\varphi(a)),k)),\varphi(a)) \\ & = & \bif{\iszero(\eta(\varphi(a)))}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(a)),k),\varphi(\varphi(a))))} \\ & = & \bif{\btrue}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(a)),k),\varphi(\varphi(a))))} \\ & \href{/posts/arithmetic-made-difficult/Booleans.html#cor-if-true} = & \delta(\varphi(a)) \\ & = & \bif{\btrue}{\delta(\varphi(a))}{} \\ & = & \bif{\iszero(\eta(\varphi(a)))}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(\eta(\varphi(a)),\varphi(\varphi(a))))} \\ & = & \Omega(\eta(\varphi(a)),\varphi(a)) \end{eqnarray*}\] as needed.
For the strong inductive step, suppose the equality holds for all \(k\) whenever \(\nleq(\eta(\varphi(a)),m)\) for some \(m\), and suppose further that \(\eta(\varphi(a)) = \next(m)\). We proceed by induction on \(k\). For the base case \(k = \zero\), of course we have \[\begin{eqnarray*} & & \Omega(\nplus(\eta(\varphi(a)),k),\varphi(a)) \\ & = & \Omega(\nplus(\eta(\varphi(a)),\zero),\varphi(a)) \\ & \href{/posts/arithmetic-made-difficult/Plus.html#thm-plus-zero-right} = & \Omega(\eta(\varphi(a)),\varphi(a)) \end{eqnarray*}\] as needed. For the inductive step, suppose the equality holds for some \(k\). Now \[\begin{eqnarray*} & & \Omega(\nplus(\eta(\varphi(a)),\next(k)),\varphi(a)) \\ & \href{/posts/arithmetic-made-difficult/Plus.html#thm-plus-next-right} = & \Omega(\next(\nplus(\eta(\varphi(a)),k)),\varphi(a)) \\ & = & \bif{\iszero(\varphi(a))}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(a)),k),\varphi(\varphi(a))))} \\ & = & \sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(a)),k),\varphi(\varphi(a)))) \\ & = & Q. \end{eqnarray*}\] Note that \(\eta(\varphi(a)) = \next(m)\), so that ((((a))),m)$, and thus \(\nplus(\eta(\varphi(\varphi(a))),u) = m\) for some \(u\). Now \[\begin{eqnarray*} & & \nplus(\eta(\varphi(a)),k) \\ & = & \nplus(\next(m),k) \\ & = & \nplus(m,\next(k)) \\ & = & \nplus(\nplus(\eta(\varphi(\varphi(a))),u),\next(k)) \\ & \href{/posts/arithmetic-made-difficult/Plus.html#thm-plus-associative} = & \nplus(\eta(\varphi(\varphi(a))),\nplus(u,\next(k))) \end{eqnarray*}\] Using the strong induction hypothesis, we have \[\begin{eqnarray*} & & Q \\ & = & \sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(\varphi(a))),\nplus(u,\next(k))),\varphi(\varphi(a)))) \\ & = & \sigma(\varphi(a),\Omega(\eta(\varphi(\varphi(a))),\varphi(\varphi(a)))) \\ & = & \sigma(\varphi(a),\Omega(\nplus(\eta(\varphi(\varphi(a))),u),\varphi(\varphi(a)))) \\ & = & \sigma(\varphi(a),\Omega(m,\varphi(\varphi(a)))) \\ & \href{/posts/arithmetic-made-difficult/Booleans.html#cor-if-false} = & \bif{\bfalse}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(m,\varphi(\varphi(a))))} \\ & = & \bif{\iszero(\eta(\varphi(a)))}{\delta(\varphi(a))}{\sigma(\varphi(a),\Omega(m,\varphi(\varphi(a))))} \\ & = & \Omega(\next(m),\varphi(a)) \\ & = & \Omega(\eta(\varphi(a)),\varphi(a)) \end{eqnarray*}\] as needed.
Now we define \(\Theta : A \rightarrow B\) by \[\Theta(a) = \Omega(\eta(a),a).\] To see that \(\Theta\) has the claimed properties, note that if \(\eta(a) = \zero\), we have \[\begin{eqnarray*} & & \Theta(a) \\ & = & \Omega(\eta(a),a) \\ & = & \Omega(\zero,a) \\ & = & \delta(a). \end{eqnarray*}\] If \(\eta(a) = \next(m)\), then \(\nleq(eta(\varphi(a)),m)\), so that \(\nplus(\eta(\varphi(a)),u) = m\) for some \(u\). Now \[\begin{eqnarray*} & & \Theta(a) \\ & = & \Omega(\eta(a),a) \\ & = & \Omega(\next(m),a) \\ & = & \bif{\iszero(\eta(a))}{\delta(a)}{\sigma(a,\Omega(m,\varphi(a)))} \\ & = & \bif{\iszero(\next(m))}{\delta(a)}{\sigma(a,\Omega(m,\varphi(a)))} \\ & \href{/posts/arithmetic-made-difficult/Unary.html#thm-iszero-next} = & \bif{\bfalse}{\delta(a)}{\sigma(a,\Omega(m,\varphi(a)))} \\ & \href{/posts/arithmetic-made-difficult/Booleans.html#cor-if-false} = & \sigma(a,\Omega(m,\varphi(a))) \\ & = & \sigma(a,\Omega(\nplus(\eta(\varphi(a)),u),\varphi(a))) \\ & = & \sigma(a,\Omega(\eta(\varphi(a)),\varphi(a))) \\ & = & \sigma(a,\Theta(\varphi(a))) \end{eqnarray*}\] as needed.
Finally we show that \(\Theta\) is unique. To this end, suppose \(\Psi : A \rightarrow B\) is a map such that \(\Psi(a) = \delta(a)\) if \(\eta(a) = \zero\) and \(\Psi(a) = \sigma(a,\Psi(\varphi(a)))\) otherwise. We show that \(\Psi(a) = \Theta(a)\) for all \(a\) by strong induction on \(\eta(a)\). For the base case \(\eta(a) = \zero\), we have \[\begin{eqnarray*} & & \Psi(a) \\ & = & \delta(a) \\ & = & \Theta(a) \end{eqnarray*}\] as needed. For the inductive step suppose the equality holds for all \(a\) such that \(\nleq(\eta(a),m)\) for some \(m\), and suppose further that \(\eta(a) = \next(m)\). Now \(\nleq(\eta(\varphi(a)),m)\), so we have \[\begin{eqnarray*} & & \Psi(a) \\ & = & \sigma(a,\Psi(\varphi(a))) \\ & = & \sigma(a,\Theta(\varphi(a))) \\ & = & \Theta(a) \end{eqnarray*}\] as needed.
Implementation
We have a couple of ways to implement \(\mnormrec\).
There’s the universal property:
mnormrec phi eta delta sigma a =
case unnext (eta a) of
Left () -> delta a
Right _ -> sigma a (mnormrec phi eta delta sigma (phi a))
And there’s the definition from the proof.