Advanced handouts

Add missing file
Co-authored-by: Mark <mark@betalupi.com>
Co-committed-by: Mark <mark@betalupi.com>
This commit is contained in:
2025-01-22 12:28:44 -08:00
parent 13b65a6c64
commit dd4abdbab0
177 changed files with 20658 additions and 0 deletions

View File

@ -0,0 +1,110 @@
% use [nosolutions] flag to hide solutions.
% use [solutions] flag to show solutions.
\documentclass[
solutions,
singlenumbering
]{../../../lib/tex/ormc_handout}
\usepackage{../../../lib/tex/macros}
\usepackage{mathtools} % for \coloneqq
% An invisible marker, used to
% draw arrows in equations.
\newcommand{\tzmr}[1]{
\tikz[
overlay,
remember picture,
right = 0.25ex
] \node (#1) {};
}
\newcommand{\tzm}[1]{
\tikz[
overlay,
remember picture
] \node (#1) {};
}
\newcommand{\lm}{\lambda}
% TODO:
% Lazy evaluation (alternate Y)
% Add a few theorems
% Better ending -> applications?
% - nix, comparison to imperative
\uptitlel{Advanced 2}
\uptitler{\smallurl{}}
\title{Lambda Calculus}
\subtitle{Prepared by Mark on \today{}}
\begin{document}
\maketitle
\hfill
\begin{minipage}{8cm}
Beware of the Turing tar pit, in which everything is possible but nothing of interest is easy.
\vspace{2ex}
Alan Perlis, \textit{Epigrams of Programming}, \#54
\end{minipage}
\hfill\null
\vspace{4mm}
\makeatletter
\if@solutions
\begin{instructornote}
\textbf{Context \& Computability:} (or, why do we need lambda calculus?)\par
\note{From Peter Selinger's \textit{Lecture Notes on Lambda Calculus}}
\vspace{2mm}
In the 1930s, several people were interested in the question: what does it mean for
a function $f : \mathbb{N} \mapsto \mathbb{N}$ to be computable? An informal definition of computability
is that there should be a pencil-and-paper method allowing a trained person to
calculate $f(n)$, for any given $n$. The concept of a pencil-and-paper method is not
so easy to formalize. Three different researchers attempted to do so, resulting in
the following definitions of computability:
\begin{itemize}
\item Turing defined an idealized computer we now call a Turing machine, and
postulated that a function is \say{computable} if and only
if it can be computed by such a machine.
\item G\"odel defined the class of general recursive functions as the smallest set of
functions containing all the constant functions, the successor function, and
closed under certain operations (such as compositions and recursion). He
postulated that a function is \say{computable} if and only
if it is general recursive.
\item Church defined an idealized programming language called the lambda calculus,
and postulated that a function is \say{computable} if and only if it can be written as a lambda term.
\end{itemize}
It was proved by Church, Kleene, Rosser, and Turing that all three computational
models were equivalent to each other --- each model defines the same class
of computable functions. Whether or not they are equivalent to the \say{intuitive}
notion of computability is a question that cannot be answered, because there is no
formal definition of \say{intuitive computability.} The assertion that they are in fact
equivalent to intuitive computility is known as the Church-Turing thesis.
\end{instructornote}
\vfill
\pagebreak
\fi
\makeatother
\input{parts/00 intro}
\input{parts/01 combinators}
\input{parts/02 boolean}
\input{parts/03 numbers}
\input{parts/04 recursion}
\input{parts/05 challenges}
\end{document}

View File

@ -0,0 +1,6 @@
[metadata]
title = "Lambda Calculus"
[publish]
handout = true
solutions = true

View File

@ -0,0 +1,461 @@
\section{Introduction}
\textit{Lambda calculus} is a model of computation, much like the Turing machine.
As we're about to see, it works in a fundamentally different way, which has a few
practical applications we'll discuss at the end of class.
\vspace{2mm}
A lambda function starts with a lambda ($\lm$), followed by the names of any inputs used in the expression,
followed by the function's output.
For example, $\lm x . x + 3$ is the function $f(x) = x + 3$ written in lambda notation.
\vspace{4mm}
Let's disect $\lm x . x + 3$ piece by piece:
\begin{itemize}[itemsep=3mm]
\item \say{$\lm$} tells us that this is the beginning of an expression. \par
$\lm$ here doesn't have a special value or definition; \par
it's just a symbol that tells us \say{this is the start of a function.}
\item \say{$\lm x$} says that the variable $x$ is \say{bound} to the function (i.e, it is used for input).\par
Whenever we see $x$ in the function's output, we'll replace it with the input of the same name.
\vspace{1mm}
This is a lot like normal function notation: In $f(x) = x + 3$, $(x)$ is \say{bound}
to $f$, and we replace every $x$ we see with our input when evaluating.
\item The dot tells us that what follows is the output of this expression. \par
This is much like $=$ in our usual function notation: \par
The symbols after $=$ in $f(x) = x + 3$ tell us how to compute the output of this function.
\end{itemize}
\problem{}
Rewrite the following functions using this notation:
\begin{itemize}
\item $f(x) = 7x + 4$
\item $f(x) = x^2 + 2x + 1$
\end{itemize}
\vfill
\pagebreak
To evaluate $\lm x . x + 3$, we need to input a value:
$$
(\lm x . x + 3)~5
$$
This is very similar to the usual way we call functions: we usually write $f(5)$. \par
Above, we define our function $f$ \say{in-line} using lambda notation, \par
and we omit the parentheses around 5 for the sake of simpler notation.
\vspace{2mm}
We evaluate this by removing the \say{$\lm$} prefix and substituting $3$ for $x$ wheverever it appears:
$$
(\lm x . \tzm{b}x + 3)~\tzmr{a}5 =
5 + 3 = 8
\begin{tikzpicture}[
overlay,
remember picture,
out=225,
in=315,
distance=0.5cm
]
\draw[->,gray,shorten >=5pt,shorten <=3pt]
(a.center) to (b.center);
\end{tikzpicture}
$$
\problem{}
Evaluate the following:
\begin{itemize}[itemsep = 2mm]
\item $(\lm x. 2x + 1)~4$
\item $(\lm x. x^2 + 2x + 1)~3$
\item $(\lm x. (\lm y. 9y) x + 3)~2$ \par
\hint{
This function has a function inside, but the evaluation process doesn't change. \\
Replace all $x$ with 2 and evaluate again.
}
\end{itemize}
\vfill
As we saw above, we denote function application by simply putting functions next to their inputs. \par
If we want to apply $f$ to $5$, we write \say{$f~5$}, without any parentheses around the function's argument.
\vspace{4mm}
You may have noticed that we've been using arithmetic in the last few problems.
This isn't fully correct: addition is not defined in lambda calculus. In fact, nothing is defined:
not even numbers!
In lambda calculus, we have only one kind of object: the function.
The only action we have is function application, which works by just like the examples above.
\vspace{2mm}
Don't worry if this sounds confusing, we'll see a few examples soon.
\pagebreak
\definition{}
The first \say{pure} functions we'll define are $I$ and $M$:
\begin{itemize}
\item $I = \lm x . x$
\item $M = \lm x . x x$
\end{itemize}
Both $I$ and $M$ take one function ($x$) as an input. \par
$I$ does nothing, it just returns $x$. \par
$M$ is a bit more interesting: it applies the function $x$ on a copy of itself.
\vspace{4mm}
Also, note that $I$ and $M$ don't have a meaning on their own. They are not formal functions. \par
Rather, they are abbreviations that say \say{write $\lm x.x$ whenever you see $I$.}
\problem{}
Reduce the following expressions. \par
\hint{
Of course, your final result will be a function. \\
Functions are the only objects we have!
}
\begin{itemize}[itemsep=2mm]
\item $I~I$
\item $M~I$
\item $(I~I)~I$
\item $\Bigl(~ \lm a .(a~(a~a)) ~\Bigr) ~ I$
\item $\Bigl(~(\lm a . (\lm b . a)) ~ M~\Bigr) ~ I$
\end{itemize}
\begin{examplesolution}
\textbf{Solution for $(I~I)$:}\par
Recall that $I = \lm x.x$. First, we rewrite the left $I$ to get $(\lm x . x )~I$. \par
Applying this function by replacing $x$ with $I$, we get $I$:
$$
I ~ I =
(\lm x . \tzm{b}x )~\tzm{a}I =
I
\begin{tikzpicture}[
overlay,
remember picture,
out=-90,
in=-90,
distance=0.5cm
]
\draw[->,gray,shorten >=5pt,shorten <=3pt]
(a.center) to (b.east);
\end{tikzpicture}
$$\null
\end{examplesolution}
\vfill
In lambda calculus, functions are left-associative: \par
$(f~g~h)$ means $((f~g)~h)$, not $(f~(g~h))$
As usual, we use parentheses to group terms if we want to override this order: $(f~(g~h)) \neq ((f~g)~h)$ \par
In this handout, all types of parentheses ( $(), [~],$ etc ) are equivalent.
\problem{}
Rewrite the following expressions with as few parentheses as possible, without changing their meaning or structure.
Remember that lambda calculus is left-associative.
\vspace{2mm}
\begin{itemize}[itemsep=2mm]
\item $(\lm x. (\lm y. \lm z. ((xz)(yz))))$
\item $((ab)(cd))((ef)(gh))$
\item $(\lm x. ((\lm y.(yx))(\lm v.v)z)u) (\lm w.w)$
\end{itemize}
\begin{solution}
$(\lm x. ((\lm y.(yx))(\lm v.v)z)u) (\lm w.w) \implies (\lm x. (\lm y.yx) (\lm v.v)~z~u) \lm w.w$
\vspace{2mm}
It's important that a function's output (everything after the dot) will continue until we hit a close-paren.
This is why we need the parentheses in the above example.
\end{solution}
\vfill
\pagebreak
\definition{Equivalence}
We say two functions are \textit{equivalent} if they differ only by the names of their variables:
$I = \lm a.a = \lm b.b = \lm \heartsuit . \heartsuit = ...$ \par
\begin{instructornote}
The idea behind this is very similar to the idea behind \say{equivalent groups} in group theory: \par
we do not care which symbols a certain group or function uses, we care about their \textit{structure}. \par
\vspace{2mm}
If we have two groups with different elements with the same multiplication table, we look at them as identical groups.
The same is true of lambda functions: two lambda functions with different variable names that behave in the same way are identical.
\end{instructornote}
\definition{}
Let $K = \lm a. (\lm b . a)$. We'll call $K$ the \say{constant function function.}
\problem{}
That's not a typo. Why does this name make sense? \par
\hint{What is $K~x$?}
\begin{solution}
$K x = \lm a . x$, which is a constant function that always outputs $x$. \par
Given an argument, $K$ returns a constant function with that value.
\end{solution}
\vfill
\problem{}
Show that associativity matters by evaluating $\bigl((M~K)~I\bigr)$ and $\bigl(M~(K~I)\bigr)$. \par
What would $M~K~I$ reduce to?
\begin{solution}
$\bigl((M~K)~I\bigr) = (K~K)~I = (\lm a.K)~I = K$ \par
$\bigl(M~(K~I)\bigr) = M~(\lm a.I) = (\lm a.I)(\lm a.I) = I$
\end{solution}
\vfill
\pagebreak
\generic{Currying:}
In lambda calculus, functions are only allowed to take one argument. \par
If we want multivariable functions, we'll have to emulate them through \textit{currying}\footnotemark{}\hspace{-1ex}.
\footnotetext{After Haskell Brooks Curry\footnotemark{}\hspace{-1ex}, a logician that contributed to the theory of functional computation.}
\footnotetext{
There are three programming languages named after him: Haskell, Brook, and Curry. \par
Two of these are functional, and one is an oddball GPU language last released in 2007.
}
\vspace{1ex}
The idea behind currying is fairly simple: we make functions that return functions. \par
We've already seen this on the previous page: $K$ takes an input $x$ and uses it to construct a constant function.
You can think of $K$ as a \say{factory} that constructs functions using the input we provide.
\problem{}<firstcardinal>
\vspace{1mm} % Slight gap for big paren
Let $C = \lm f. \Bigl[\lm g. \Bigl( \lm x. [~ f(g(x)) ~] \Bigr)\Bigr]$. For now, we'll call it the \say{composer.} \par
\note[Note]{We could also call $C$ the \say{right-associator.} Why?}
\vspace{3mm}
$C$ has three \say{layers} of curry: it makes a function ($\lm g$) that makes another function ($\lm x$). \par
If we look closely, we'll find that $C$ pretends to take three arguments.
\vspace{1mm}
What does $C$ do? Evaluate $(C~a~b~x)$ for arbitrary expressions $a, b,$ and $x$. \par
\hint{Evaluate $(C~a)$ first. Remember, function application is left-associative.}
\vfill
\problem{}
Using the definition of $C$ above, evaluate $C~M~I~\star$ \par
Then, evaluate $C~I~M~I$ \par
\note[Note]{$\star$ represents an arbitrary expression. Treat it like an unknown variable.}
\vfill
As we saw above, currying allows us to create multivariable functions by nesting single-variable functions.
You may have notice that curried expressions can get very long. We'll use a bit of shorthand to make them more palatable:
If we have an expression with repeated function definitions, we'll combine their arguments under one $\lm$.
\vspace{1ex}
For example, $A = \lm f .[ \lm a . f(f(a))]$ will become $A = \lm fa . f(f(a))$
\problem{}
Rewrite $C = \lm f.\lm g.\lm x. (g(f(x)))$ from \ref{firstcardinal} using this shorthand.
\vspace{25mm}
Remember that this is only notation. \textbf{Curried functions are not multivariable functions, they are simply shorthand!}
Any function presented with this notation must still be evaluated one variable at a time, just like an un-curried function.
Substituting all curried variables at once will cause errors.
\pagebreak
%\iftrue
\iffalse
\generic{$\alpha$-Conversion:}
There is one more operation we need to discuss. Those of you that have worked with any programming language may
find that this section sounds like something you've seen before.
\vspace{2mm}
Variables inside functions are \say{scoped.} We must take care to keep separate variables separate.
For example, take the functions \par
$A = \lm a b . a$ \par
$B = \lm b . b$
\vspace{2ex}
We could say that $(A~B) = \lm b . (\lm b . b)$, and therefore
$$
((A~B)~I)
= (~ (\lm \tzm{b}b . (\lm b . b))~\tzmr{a}I ~)
= \lm I . I
\begin{tikzpicture}[
overlay,
remember picture,
out=225,
in=315,
distance=0.5cm
]
\draw[->,gray,shorten >=5pt,shorten <=3pt]
(a.center) to (b.center);
\end{tikzpicture}
$$
Which is, of course, incorrect. $\lm I . I$ is not a valid function.
This problem arises because both $A$ and $B$ use the input $b$.
However, each $b$ is \say{bound} to a different function:
One $b$ is bound to $A$, and the other to $B$. They are therefore distinct.
\vspace{2ex}
Let's rewrite $B$ as $\lm b_1 . b_1$ and try again: $(A~B) = \lm b . ( \lm b_1 . b_1) = \lm bb_1 . b_1$ \par
Now, we correctly find that $(A~B~I) = (\lm bc . c)~I = \lm c . c = B = I$.
\fi
\problem{}
Let $Q = \lm abc.b$. Reduce $(Q~a~c~b)$. \par
\hint{
You may want to rename a few variables. \\
The $a,b,c$ in $Q$ are different than the $a,b,c$ in the expression!
}
\begin{solution}
I'll rewrite $(Q~a~c~b)$ as $(Q~a_1~c_1~b_1)$:
\begin{align*}
Q = (\lm abc.b) &= (\lm a.\lm b.\lm c.b) \\
(\lm a.\lm b.\lm c.b)~a_1 &= (\lm b.\lm c.b) \\
(\lm b.\lm c.b)~c_1 &= (\lm c.c_1) \\
(\lm c.c_1)~b_1 &= c_1
\end{align*}
\end{solution}
\vfill
\problem{}
Reduce $((\lm a.a)~\lm bc.b)~d~\lm eg.g$
\begin{solution}
$((\lm a.a)~\lm bc.b)~d~\lm eg.g$ \\
$= (\lm bc.b)~d~\lm eg.g$ \\
$= (\lm c.d)~\lm eg.g$ \\
$= d$
\end{solution}
\vfill
\pagebreak

View File

@ -0,0 +1,42 @@
\section{Combinators}
\definition{}
A \textit{free variable} in a $\lm$-expression is a variable that isn't bound to any input. \par
For example, $b$ is a free variable in $(\lm a.a)~b$.
\definition{Combinators}
A \textit{combinator} is a lambda expression with no free variables.
\vspace{1mm}
Notable combinators are often named after birds.\hspace{-0.5ex}\footnotemark{} We've already met a few: \par
The \textit{Idiot}, $I = \lm a.a$ \par
The \textit{Mockingbird}, $M = \lm f.ff$ \par
The \textit{Cardinal}, $C = \lm fgx.(~ f(g(x)) ~)$
The \textit{Kestrel}, $K = \lm ab . a$
\problem{}
If we give the Kestrel two arguments, it does something interesting: \par
It selects the first and rejects the second. \par
Convince yourself of this fact by evaluating $(K~\heartsuit~\star)$.
\vfill
\problem{}<kitedef>
Modify the Kestrel so that it selects its \textbf{second} argument and rejects the first. \par
\begin{solution}
$\lm ab . b$.
\end{solution}
\vfill
\problem{}
We'll call the combinator from \ref{kitedef} the \textit{Kite}, $KI$. \par
Show that we can also obtain the kite by evaluating $(K~I)$.
\vfill
\pagebreak

View File

@ -0,0 +1,77 @@
\section{Boolean Algebra}
The Kestrel selects its first argument, and the Kite selects its second. \par
Maybe we can somehow put this \say{choosing} behavior to work...
\vspace{1ex}
Let $T = K\phantom{I} = \lm ab . a$ \par
Let $F = KI = \lm ab . b$
\problem{}
Write a function $\text{NOT}$ so that $(\text{NOT} ~ T) = F$ and $(\text{NOT}~F) = T$. \par
\hint{What is $(T~\heartsuit~\star)$? How about $(F~\heartsuit~\star)$?}
\begin{solution}
$\text{NOT} = \lm a . (a~F~T)$
\end{solution}
\vfill
\problem{}
How would \say{if} statements work in this model of boolean logic? \par
Say we have a boolean $B$ and two expressions $E_T$ and $E_F$.
Can we write a function that evaluates to $E_T$ if $B$ is true, and to $E_F$ otherwise?
\vfill
\pagebreak
\problem{}
Write functions $\text{AND}$, $\text{OR}$, and $\text{XOR}$ that satisfy the following table.
\begin{center}
\begin{tabular}{|| c c || c | c | c ||}
\hline
$A$ & $B$ & $(\text{AND}~A~B)$ & $(\text{OR}~A~B)$ & $(\text{XOR}~A~B)$ \\
\hline\hline
F & F & F & F & F \\
\hline
F & T & F & T & T \\
\hline
T & F & F & T & T \\
\hline
T & T & T & T & F \\
\hline
\end{tabular}
\end{center}
\begin{solution}
There's more than one way to do this, of course.
\begin{align*}
\text{AND} &= \lm ab . (a~b~F) = \lm ab . aba \\
\text{OR} &= \lm ab . (a~T~b) = \lm ab . aab \\
\text{XOR} &= \lm ab . (a~ (\text{NOT}~b) ~b)
\end{align*}
Another clever solution is $\text{OR} = \lm ab.(M~a~b)$
\end{solution}
\vfill
\problem{}
To complete our boolean algebra, construct the boolean equality check EQ. \par
What inputs should it take? What outputs should it produce?
\begin{solution}
$\text{EQ} = \lm ab . [a~(bTF)~(bFT)] = \lm ab . [a~b~(\text{NOT}~b)]$
\vspace{1ex}
$\text{EQ} = \lm ab . [\text{NOT}~(\text{XOR}~a~b)]$
\end{solution}
\vfill
\pagebreak

View File

@ -0,0 +1,175 @@
\section{Numbers}
Since the only objects we have in $\lm$ calculus are functions, it's natural to think of quantities as \textit{adverbs} (once, twice, thrice,...) rather than \textit{nouns} (one, two, three ...)
\vspace{1ex}
We'll start with zero. If our numbers are \textit{once,} \textit{twice,} and \textit{twice}, it may make sense to make zero \textit{don't}. \par
Here's our \textit{don't} function: given a function and an input, don't apply the function to the input.
$$
0 = \lm fa.a
$$
If you look closely, you'll find that $0$ is equivalent to the false function $F$.
\problem{}
Write $1$, $2$, and $3$. We will call these \textit{Church numerals}.\hspace{-0.5ex}\footnotemark{} \\
\note{\textit{Note:} This problem read aloud is \say{Define \textit{once}, \textit{twice}, and \textit{thrice}.}}
\footnotetext{after Alonzo Church, the inventor of lambda calculus and these numerals. He was Alan Turing's thesis advisor.}
\begin{solution}
$1$ calls a function once on its argument: \par
$1 = \lm fa . (f~a)$.
\vspace{1ex}
Naturally, \par
$2 = \lm fa . [~f~(f~a)~]$ \par
$3 = \lm fa . [~f~(f~(f~a))~]$
\vspace{1ex}
The round parentheses are \textit{essential}. Our lambda calculus is left-associative! \par
Also, note that zero is false and one is the (two-variable) identity.
\end{solution}
\vfill
\problem{}
What is $(4~I)~\star$?
\vfill
\problem{}
What is $(3~NOT~T)$? \par
How about $(8~NOT~F)$?
\vfill
\pagebreak
\problem{}
Peano's axioms state that we only need a zero element and a \say{successor} operation to
build the natural numbers. We've already defined zero.
Now, create a successor operation so that $1 \coloneqq S(0)$, $2 \coloneqq S(1)$, and so on. \par
\hint{A good signature for this function is $\lm nfa$, or more clearly $\lm n.\lm fa$. Do you see why?}
\begin{solution}
$S = \lm n. [\lm fa . f~(n~f~a)] = \lm nfa . [f~(n~f~a)]$
\vspace{1ex}
Do $f$ $n$ times, then do $f$ one more time.
\end{solution}
\vfill
\problem{}
Verify that $S(0) = 1$ and $S(1) = 2$.
\vfill
\pagebreak
Assume that only Church numerals will be passed to the functions in the following problems. \par
We make no promises about their output if they're given anything else.
\problem{}
Define a function ADD that adds two Church numerals.
\begin{solution}
$\text{ADD} = \lm mn . (m~S~n) = \lm mn . (n~S~m)$
\end{solution}
\begin{instructornote}
Defining \say{equivalence} is a bit tricky. The solution above illustrates the problem pretty well.
\note{Note: The notions of \say{extensional} and \say{intentional} equivalence may be interesting in this context. Do some reading on your own.
}
\vspace{4ex}
These two definitions of ADD are equivalent if we apply them to Church numerals. If we were to apply these two versions of ADD to functions that behave in a different way, we'll most likely get two different results! \\
As a simple example, try applying both versions of ADD to the Kestrel and the Kite.
\vspace{1ex}
To compare functions that aren't $\alpha$-equivalent, we'll need to restrict our domain to functions of a certain form, saying that two functions are equivalent over a certain domain. \\
\end{instructornote}
\vfill
\problem{}
Design a function MULT that multiplies two numbers. \par
\hint{The easy solution uses ADD, the elegant one doesn't. Find both!}
\begin{solution}
$\text{MULT} = \lm mn . [m~(\text{ADD}~n)~m]$
$\text{MULT} = \lm mnf . [m~(n~f)]$
\end{solution}
\vfill
\pagebreak
\problem{}
Define the functions $Z$ and $NZ$. $Z$ should reduce to $T$ if its input was zero, and $F$ if it wasn't. \par
$NZ$ does the opposite. $Z$ and $NZ$ should look fairly similar.
\vspace{1ex}
\begin{solution}
$Z\phantom{N} = \lm n .[n~(\lm a.F)~T]$ \par
$NZ = \lm n .[n~(\lm a.T)~F]$
\end{solution}
\vfill
\problem{}
Design an expression PAIR that constructs two-value tuples. \par
For example, say $A = \text{PAIR}~1~2$. Then, \par
$(A~T)$ should reduce to $1$ and $(A~F)$ should reduce to $2$.
\begin{solution}
$\text{PAIR} = \lm ab . \lm i . (i~a~b) = \lm abi.iab$
\end{solution}
\vfill
From now on, I'll write (PAIR $A$ $B$) as $\langle A,B \rangle$. \par
Like currying, this is only notation. The underlying logic remains the same.
\pagebreak
\problem{}<shiftadd>
Write a function $H$, which we'll call \say{shift and add.} \par
It does exactly what it says on the tin:
\vspace{1ex}
Given an input pair, it should shift its second argument left, then add one. \par
$H~\langle 0, 1 \rangle$ should reduce to $\langle 1, 2\rangle$ \par
$H~\langle 1, 2 \rangle$ should reduce to $\langle 2, 3\rangle$ \par
$H~\langle 10, 4 \rangle$ should reduce to $\langle 4, 5\rangle$
\begin{solution}
$H = \lm p . \Bigl\langle~(p~F)~,~S(p~F)~\Bigr\rangle$
\vspace{1ex}
Note that $H~\langle 0, 0 \rangle$ reduces to $\langle 0, 1 \rangle$
\end{solution}
\vfill
\problem{}<decrement>
Design a function $D$ that un-does $S$. That means \par
$D(1) = 0$, $D(2) = 1$, etc. $D(0)$ should be zero. \par
\hint{$H$ will help you make an elegant solution.}
\begin{solution}
$D = \lm n . \Bigl[(~n~H~\langle 0, 0 \rangle~)~T\Bigr]$
\end{solution}
\vfill
\pagebreak

View File

@ -0,0 +1,162 @@
\section{Recursion}
%\iftrue
\iffalse
You now have a choice. Choose wisely --- there's no going back.
\begin{tcolorbox}[
breakable,
colback=white,
colframe=gray,
arc=0pt, outer arc=0pt
]
\raggedright
\textbf{Take the red pill:} You stay on this page and try to solve \ref{thechallenge}. \par
This will take a while, and it's very unlikely you'll finish before class ends.
\vspace{4mm}
I strongly prefer this option. It's not easy, but you'll be very happy if you solve it yourself.
This is a chance to build your own solution to a fundamental problem in this field, just as
Curry, Church, and Turing did when first developing the theory of lambda calculus.
- Mark
\end{tcolorbox}
\begin{tcolorbox}[
breakable,
colback=white,
colframe=gray,
arc=0pt, outer arc=0pt
]
\textbf{Take the blue pill:} You skip this problem and turn the page.
Half of the answer to \ref{thechallenge} will be free, and the rest will be
broken into smaller steps. This is how we usually learn out about interesting
mathematics, both in high school and in university.
\vspace{2mm}
This path isn't as rewarding as the one above, but it is well-paved
and easier to traverse.
\end{tcolorbox}
\problem{}<thechallenge>
Can you find a way to recursively call functions in lambda calculus? \par
Find a way to define a recursive factorial function. \par
\note{$A = (\lm a. A~a)$ doesn't count. You can't use a macro inside itself.}
\vfill
\pagebreak
\fi
Say we want a function that computes the factorial of a positive integer. Here's one way we could define it:
$$
x! = \begin{cases}
x \times (x-1)! & x \neq 0 \\
1 & x = 0
\end{cases}
$$
We cannot re-create this in lambda calculus, since we aren't given a way to recursively call functions.
\vspace{2mm}
One could think that $A = \lm a. A~a$ is a recursive function. In fact, it is not. \par
Remember that such \say{definitions} aren't formal structures in lambda calculus. \par
They're just shorthand that simplifies notation.
\begin{instructornote}
We're talking about recursion, and \textit{computability} isn't far away. At one point or another, it may be good to give the class a precise definition of \say{computable by lambda calculus:}
\vspace{4ex}
Say we have a device that reduces a $\lm$ expression to $\beta$-normal form. We give it an expression, and the machine simplifies it as much as it can and spits out the result.
\vspace{1ex}
An algorithm is \say{computable by lambda calculus} if we can encode its input in an expression that resolves to the algorithm's output.
\end{instructornote}
\problem{}
Write an expression that resolves to itself. \par
\hint{Your answer should be quite short.}
\vspace{1ex}
This expression is often called $\Omega$, after the last letter of the Greek alphabet. \par
$\Omega$ useless on its own, but it gives us a starting point for recursion. \par
\begin{solution}
$\Omega = M~M = (\lm x . xx) (\lm x . xx)$
\vspace{1mm}
An uninspired mathematician might call the Mockingbird $\omega$, \say{little omega}.
\end{solution}
\vfill
\pagebreak
\definition{}
This is the \textit{Y-combinator}. You may notice that it's just $\Omega$ put to work.
$$
Y = \lm f . (\lm x . f(x~x))(\lm x . f(x~x))
$$
\problem{}
What does this thing do? \par
Evaluate $Y f$.
%\vfill
%\definition{}
%We say $x$ is a \textit{fixed point} of a function $f$ if $f(x) = x$.
%\problem{}
%Show that $Y F$ is a fixed point of $F$.
%\vfill
%\problem{}
%Let $b = (\lm xy . y(xxy))$ and $B = b ~ b$. \par
%Let $N = B F$ for an arbitrary lambda expression $F$. \par
%Show that $F N = N$.
%\vfill
%\problem{Bonus}
%Find a fixed-point combinator that isn't $Y$ or $\Theta$.
\vfill
\pagebreak

View File

@ -0,0 +1,130 @@
\section{Challenges}
Do \ref{Yfac} first, then finish the rest in any order.
\problem{}<Yfac>
Design a recursive factorial function using $Y$.
\begin{solution}
$\text{FAC} = \lm yn.[Z~n][1][\text{MULT}~n~(y~(\text{D}~n))]$
To compute the factorial of 5, evaluate $(\text{Y}~\text{FAC}~5)$.
\end{solution}
\vfill
\problem{}
Design a non-recursive factorial function. \par
\note{This one is easier than \ref{Yfac}, but I don't think it will help you solve it.}
\begin{solution}
$\text{FAC}_0 = \lm p .
\Bigl\langle~~
\Bigl[D~(p~t)\Bigr]
~,~
\Bigl[\text{MULT}~(p~T)~(p~F)\Bigr]
~~\Bigr\rangle
$
\vspace{2ex}
$
\text{FAC} = \lm n .
\bigl( n~\text{FAC}_0~\langle n, 1 \rangle \bigr)
$
\end{solution}
\vfill
\problem{}
Solve \ref{decrement} without using $H$. \par
In \ref{decrement}, we created the \say{decrement} function.
\begin{solution}
One solution is below. Can you figure out how it works? \par
\vspace{1ex}
$
D_0 =
\lm p . \Bigl[p~T\Bigr]
\Bigl\langle
F ~,~ p~F
\Bigr\rangle
\Bigl\langle
F
~,~
\bigl\langle
p~F~T ~,~ ( (p~F~T)~(P~F~F) )
\bigr\rangle
\Bigr\rangle
$
\vspace{1ex}
$
D = \lm nfa .
\Bigl(
n D_0 \Bigl\langle T, \langle f, a \rangle \Bigr\rangle
\Bigr)~F~F
$
\end{solution}
\vfill
\problem{}
Using pairs, make a \say{list} data structure. Define a GET function, so that $\text{GET}~L~n$ reduces to the nth item in the list.
$\text{GET}~L~0$ should give the first item in the list, and $\text{GET}~L~1$, the \textit{second}. \par
Lists have a defined length, so you should be able to tell when you're on the last element.
\begin{solution}
One possible implementation is
$\Bigl\langle
\langle \text{is last} ~,~ \text{item} \rangle
~,~
\text{next}...
\Bigr\rangle$, where:
\vspace{1ex}
\say{is last} is a boolean, true iff this is the last item in the list. \par
\say{item} is the thing you're storing \par
\say{next...} is another one of these list fragments.
It doesn't matter what \say{next} is in the last list fragment. A dedicated \say{is last} slot allows us to store arbitrary functions in this list.
\vspace{1ex}
Here, $\text{GET} = \lm nL.[(n~L~F)~T~F$]
This will break if $n$ is out of range.
\end{solution}
\vfill
\pagebreak
\problem{}
Write a lambda expression that represents the Fibonacci function: \par
$f(0) = 1$, $f(1) = 1$, $f(n + 2) = f(n + 1) + f(n)$.
\vfill
\problem{}
Write a lambda expression that evaluates to $T$ if a number $n$ is prime, and to $F$ otherwise.
\vfill
\problem{}
Write a function MOD so that $(\text{MOD}~a~b)$ reduces to the remainder of $a \div b$.
\vfill
\problem{Bonus}
Play with \textit{Lamb}, an automatic lambda expression evaluator. \par
\url{https://git.betalupi.com/Mark/lamb}
\pagebreak