From 12c677f2da29a11b1043ea32ef8f47212360e455 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 13 Nov 2022 13:02:25 -0800 Subject: [PATCH] Added Crypto & Lambda handouts --- Advanced/Cryptography/main.tex | 34 +++ Advanced/Cryptography/parts/challenge.tex | 146 ++++++++++ Advanced/Cryptography/parts/part 1.tex | 129 +++++++++ Advanced/Cryptography/parts/part 2.tex | 68 +++++ Advanced/Cryptography/parts/part 3.tex | 169 ++++++++++++ Advanced/Lambda Calculus/main.tex | 64 +++++ Advanced/Lambda Calculus/parts/00 intro.tex | 254 ++++++++++++++++++ .../Lambda Calculus/parts/01 combinators.tex | 47 ++++ Advanced/Lambda Calculus/parts/02 boolean.tex | 71 +++++ Advanced/Lambda Calculus/parts/03 numbers.tex | 226 ++++++++++++++++ .../Lambda Calculus/parts/04 recursion.tex | 67 +++++ .../Lambda Calculus/parts/05 challenges.tex | 87 ++++++ 12 files changed, 1362 insertions(+) create mode 100755 Advanced/Cryptography/main.tex create mode 100755 Advanced/Cryptography/parts/challenge.tex create mode 100755 Advanced/Cryptography/parts/part 1.tex create mode 100755 Advanced/Cryptography/parts/part 2.tex create mode 100755 Advanced/Cryptography/parts/part 3.tex create mode 100755 Advanced/Lambda Calculus/main.tex create mode 100755 Advanced/Lambda Calculus/parts/00 intro.tex create mode 100755 Advanced/Lambda Calculus/parts/01 combinators.tex create mode 100755 Advanced/Lambda Calculus/parts/02 boolean.tex create mode 100755 Advanced/Lambda Calculus/parts/03 numbers.tex create mode 100755 Advanced/Lambda Calculus/parts/04 recursion.tex create mode 100755 Advanced/Lambda Calculus/parts/05 challenges.tex diff --git a/Advanced/Cryptography/main.tex b/Advanced/Cryptography/main.tex new file mode 100755 index 0000000..6f3652c --- /dev/null +++ b/Advanced/Cryptography/main.tex @@ -0,0 +1,34 @@ +% https://git.betalupi.com/Mark/latex +% use [nosolutions] flag to hide solutions. +% use [solutions] flag to show solutions. +% Last built with version 1.1.0 +\documentclass[ + solutions, + singlenumbering +]{ormc_handout} + +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{multicol} +\usepackage{subfiles} + + +\begin{document} + + \maketitle + + + {Intro to Cryptography} + {Prepared by Mark on \today{}} + + \vspace{3ex} + + \subfile{parts/part 1} + + \subfile{parts/part 2} + + \subfile{parts/part 3} + + \subfile{parts/challenge} + +\end{document} diff --git a/Advanced/Cryptography/parts/challenge.tex b/Advanced/Cryptography/parts/challenge.tex new file mode 100755 index 0000000..616800a --- /dev/null +++ b/Advanced/Cryptography/parts/challenge.tex @@ -0,0 +1,146 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + + \section{Challenge Problems} + + + \problem{} + Prove \ref{mod_has_inverse}: \\ + $a$ has an inverse mod $m$ iff $\gcd(a, m) = 1$ \\ + \begin{hint} + To prove an iff statement, prove each direction separately: \\ + Assume that the left side is true and show that left $\implies$ right, \\ + then do the reverse. + \end{hint} + + + \begin{solution} + Assume $a^\star$ is the inverse of $a \pmod{m}$. \\ + Then $a^\star \times a \equiv 1 \pmod{m}$ \\ + + Therefore, $aa^\star - 1 = km$, and $aa^\star - km = 1$ \\ + We know that $\gcd(a, m)$ divides $a$ and $m$, therefore $\gcd(a, m)$ must divide $1$. \\ + $\gcd(a, m) = 1$ \\ + + Now, assume $\gcd(a, m) = 1$. \\ + By the Extended Euclidean Algorithm, we can find $(u, v)$ that satisfy $au+mv=1$ \\ + So, $au-1 = mv$. \\ + $m$ divides $au-1$, so $au \equiv 1 \pmod{m}$ \\ + $u$ is $a^\star$. + \end{solution} + + + \vfill + + + \problem{} + The Euclidean Algorithm (From \ref{euclid_algorithm}) can be written as follows: \\ + + Assume $a > b$. + Set $e_0 = a$ and $e_1 = b$. \\ + Let $e_{n+1} = \text{remainder}(r_{n-1} \div r_{n})$ \\ + Stop when $e_{k} = 0$. + Then, $\gcd(a, b) = e_{k-1}$. \\ + + Let $F_n$ be the $n^{\text{th}}$ Fibonacci number. ($F_0 = 0$; $F_1 = 1$; $F_2 = 1$; $\dots$)\\ + Show that if the Euclidean algorithm requires $n$ steps for an input $(a, b)$, then $a \geq F_{n+2}$ and $b \geq F_{n+1}$. + + (In other words, show that the longest-running input of a given size is a Fibonacci pair.) + + \begin{solution} + The easiest way to go about this is induction on $n$: \\ + + \textcolor{gray}{\textit{Base Case:}} + + If $n = 1$, $b$ divides $a$ with no remainder, and the smallest possible $a, b$ for which this is true is $(2, 1) = (F_3, F_2)$. + + \linehack{} + + \textcolor{gray}{\textit{Induction:}} + + Assume that for $n$ steps, $a \geq F_{n+2}$ and $b \geq F_{n+1}$. + + Now, say the algorithm takes $n+1 = m$ steps. \\ + + The first step gives us $a = q_0b + r_0$ \\ + Therefore, the pair $(b, r_0)$ must take $m-1$ steps. \\ + We thus know that $b \geq F_{m+1}$ and $r_0 \geq F_m$ \hfill \textcolor{gray}{by our induction hypothesis} \\ + Therefore, $a = q_0b + r_0 \geq b + r_0$ \\ + But $b + r_0 = F_{m+1} + F_{m} = F_{m+2}$, \\ + so $a \geq F_{m+2}$. + \end{solution} + + \vfill + + \problem{Chinese Remainder Theorem} + There are certain things whose number is unknown. If we count them by threes, we have two left over; by fives, we have three left over; and by sevens, two are left over. How many things are there? + + \begin{solution} + $x \equiv 2 \pmod{3}$ \\ + $x \equiv 3 \pmod{5}$ \\ + $x \equiv 2 \pmod{7}$ \\ + + $x = 23 + 105k\ \forall k \in \mathbb{Z}$ + \end{solution} + + \vfill + + \problem{} + Show that if $p$ is prime, $\binom{p}{i} \equiv 0 \pmod{p}$ + for $0 < i < p$. + + \begin{solution} + $\binom{p}{i} = \frac{p!}{i!(p-i)!}$ tells us that $i!(p-i)!$ divides $p! = p(p-1)!$. \\ + However, $i!(p-i)!$ and $p$ are coprime, since all factors of $i!(p-i)!$ are smaller than $p$. \\ + Therefore, $i!(p-i)!$ must divide $(p-1)!$ \\ + + So, $\binom{p}{i} = p \times \frac{(p-1)!}{i!(p-i)!}$, and $\binom{p}{i} \equiv 0 \pmod{p}$. + \end{solution} + + \vfill + + \problem{Fermat's Little Theorem} + Show that if $p$ is prime and $a \not\equiv 0 \pmod{p}$, then $a^{p-1} \equiv 1 \pmod{p}$. \\ + You may want to use \ref{flt_prereq}. + + \begin{hint} + It may be easier to show that $a^p \equiv a \pmod{p}$ + \end{hint} + + + \begin{solution} + Use induction: + + $1 \equiv 1 \pmod{p}$ \\ + + Using \ref{flt_prereq} and the binomial theorem, we have + + $2^p = (1 + 1)^p = 1 + \binom{p}{1} + \binom{p}{2} + \dots + \binom{p}{p-1} + 1 \equiv 1 + 0 + ... + 0 + 1 \equiv 2 \pmod{p}$ \\ + + Then, + + $3^p = (1 + 2)^p = 1 + \binom{p}{1}2 + \binom{p}{2}2^2 + \dots + \binom{p}{p-1}2^{p-1} + 2^p \equiv 1 + 0 + ... + 0 + 2 \equiv 3 \pmod{p}$ \\ + + We can repeat this for all $a$. This proof can be presented more formally with a bit of induction. + + \end{solution} + + \vfill + + + %\problem{} + %Prove \ref{theorem:gcd_abc}: \\ + %For any integers $a, b, c$, \\ + %$\gcd(ac + b, a) = \gcd(a, b)$\\ + + %\begin{solution} + % This problem is hard, \\ + % I'll write a solution eventually. + %\end{solution} + + %\vfill + + [Note on \ref{eua_runtime}] This proof can be used to show that the Euclidean algorithm finishes in logarithmic time, and it is the first practical application of the Fibonacci numbers. If you have finished all challenge problems, finish the proof: show that the Euclidean runs in $O(\log{n})$ + \pagebreak +\end{document} diff --git a/Advanced/Cryptography/parts/part 1.tex b/Advanced/Cryptography/parts/part 1.tex new file mode 100755 index 0000000..b8f7c60 --- /dev/null +++ b/Advanced/Cryptography/parts/part 1.tex @@ -0,0 +1,129 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + \section{The Euclidean Algorithm} + + \definition{} + The \textit{greatest common divisor} of $a$ and $b$ is the greatest integer that divides both $a$ and $b$. \\ + We denote this number with $\gcd(a, b)$. For example, $\gcd(45, 60) = 15$. + + + \theorem{The Division Algorithm} + Given two integers $a, b$, we can find two integers $q, r$, where $0 \leq r < b$ and $a = qb + r$. \\ + In other words, we can divide $a$ by $b$ to get $q$ remainder $r$. + + \theorem{} + For any integers $a, b, c$, \\ + $\gcd(ac + b, a) = \gcd(a, b)$ + + \problem{} + Find $\gcd(20, 14)$ by hand. + + \begin{solution} + $\gcd(20, 14) = 2$ + \end{solution} + + \vfill + + \problem{} + Using the theorems above, detail an algorithm for finding $\gcd(a, b)$.\\ + Then, compute $\gcd(1610, 207)$ by hand. \\ + Have an instructor check your work before moving on. + + \begin{solution} + Using \ref{gcd_abc} and the division algorthm, + + % Minipage prevents column breaks inside body + \begin{multicols}{2} + \begin{minipage}{\columnwidth} + $\gcd(1610, 207)$ \\ + $= \gcd(207, 161)$ \\ + $= \gcd(161, 46)$ \\ + $= \gcd(46, 23)$ \\ + $= \gcd(23, 0) = 23$ \\ + \end{minipage} + + \columnbreak + + \begin{minipage}{\columnwidth} + $1610 = 207 \times 7 + 161$ \\ + $207 = 161 \times 1 + 46$ \\ + $161 = 46 \times 3 + 23$ \\ + $46 = 23 \times 2 + 0$ \\ + \end{minipage} + \end{multicols} + \end{solution} + + \vfill + \pagebreak + + \problem{Divide and Conquer} + If we are given $a, b, c$, when can we find $u, v$ that satisfy $au + bv = c$? + + \problempart{Divide} + Show that if we find a solution $(u, v)$ to $au + bv = \gcd(a, b)$, we can easily find a $(u, v)$ for any other value of $c$. \\ + \textcolor{gray}{\textit{Note: } We are not looking for \textit{all} $(u, v)$ that solve $au + bv = c$, we are looking for an easy way to find \textit{any} $(u, v)$.} + + \begin{solution} + Note that $\gcd(a, b)$ divides both a and b. \\ + Therefore, any $c$ must be divisible by $\gcd(a, b)$. + The smallest such $c$ is $\gcd(a, b)$ itself, and we can get all other tuples $(u, v, c)$ by scaling. + \end{solution} + + \vfill + + \problempart{Conquer} + Using the output of your algorithm\footnotemark{} from \ref{euclid_algorithm}, + \footnotetext{Your solution to \ref{euclid_algorithm} is called the \textit{Euclidean Algorithm}} + \begin{itemize} + \item[-] find a pair $(u, v)$ that satisfies $20u + 14v = \gcd(20, 14)$ + \item[-] find a pair $(u, v)$ that satisfies $541u + 34v = \gcd(541, 34)$ \\ + % gcd = 1 + % u = 11; v = -175 + \end{itemize} + For which numbers $c$ can we find a $(u, v)$ so that $541u + 34v = c$? \\ + For every such $c$, what are $u$ and $v$? + + \begin{solution} + + Using the output of the Euclidean Algorithm, we can use substitution and a bit of algebra to solve such problems. Consider the following example: + + \begin{multicols}{2} + \begin{minipage}{\columnwidth} + \textit{Euclidean Algorithm:} \\ + $20 = 14 \times 1 + 6$ \\ + $14 = 6 \times 2 + 2$ \\ + $6 = 2 \times 3 + 0$ \\ + \end{minipage} + + \columnbreak + + \begin{minipage}{\columnwidth} + \textit{Rearranged:} \\ + $6 = 20 - 14 \times 1$ \\ + $2 = 14 - 6 \times 2 = \gcd(20, 14)$ \\ + \end{minipage} + \end{multicols} + + Using the right table, we can replace $6$ in $2 = 14 - 6 \times 2$ to get + $2 = 14 - (20 - 14) \times 2$, \\ + which gives us $2 = \gcd(20, 14) = (3)14 + (-2)20$. \\ + + \textcolor{gray}{\textit{Note to instructors:} You can present the $(20, 14)$ case as an example.} + + \linehack{} + + $(-2)20 + (3)14 = \gcd(20, 14) = 2$ \\ + $(11)541 + (-175)34 = \gcd(541, 34) = 1$ + + \linehack{} + + We can find a solution $(u, v)$ when $c$ is any integer multiple of $\gcd(541, 34)$. \\ + If $c = k \times \gcd(541, 34)$, \\ + $u = k \times u_0 = 11k$ and $v = k \times v_0 = -175k$. \\ + (See Part A) + + \end{solution} + \vfill + \pagebreak +\end{document} diff --git a/Advanced/Cryptography/parts/part 2.tex b/Advanced/Cryptography/parts/part 2.tex new file mode 100755 index 0000000..11194d7 --- /dev/null +++ b/Advanced/Cryptography/parts/part 2.tex @@ -0,0 +1,68 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + \section{Modular Arithmetic} + + \definition{} + We say that $a, b$ are equivalent mod $m$ if $m$ divides $a - b$. \\ + If $a$ is equivalent to $b$ mod $m$, we write $a \equiv b \pmod{m}$. \\ + You can think of $b$ as the remainder of $a \div m$: + \begin{itemize} + \item[] $32 \equiv 2 \pmod{6}$ + \item[] $4 \equiv 4 \pmod{6}$ + \item[] $-2 \equiv 4 \pmod{6}$ + \end{itemize} + + \problem{} + Complete the following: + \begin{itemize} + \item[] $87 \equiv ? \pmod{12}$ \hspace{3em} \textcolor{gray}{(Your answer should be between $0$ and $12$)} + \item[] $13 \equiv 2 \pmod{?}$ + \item[] $? \equiv 1 \pmod{9}$ + \end{itemize} + + \begin{solution} + \begin{itemize} + \item[] $87 \equiv 3 \pmod{12}$ + \item[] $13 \equiv 2 \pmod{11}$ + \item[] $(9k + 1) \equiv 1 \pmod{9}\ \forall k \in \mathbb{Z}$ + \end{itemize} + \end{solution} + + \vfill + + \definition{} + The inverse of $a$ mod $m$ is an integer $a^\star$ so that \\ + $a \times a^\star \equiv 1 \pmod{m}$. \\ + Note that not every $a$ has an inverse mod $m$. + + \theorem{} + $a$ has an inverse mod $m$ iff $\gcd(a, m) = 1$ \\ + \textcolor{gray}{\textit{The proof of this theorem is left as a challenge problem.}} + + \problem{D\'ej\`a vu?} + Find the inverse of $20 \pmod{14}$, if one exists. \\ + Find the inverse of $34 \pmod{541}$, if one exists. + + \begin{solution} + $20^\star$ does not exist mod $14$, by \ref{mod_has_inverse}. \\ + $34^\star \equiv -175 \equiv 366 \pmod{541}$. + See \ref{general_inverse} for an explanation. + \end{solution} + + \vfill + + \problem{} + In general, how can we find the inverse of $a \pmod{p}$?\\ + (Assume $p$ is prime.) + + \begin{solution} + We need an $a^\star$ so that $a \times a^\star \equiv 1 \pmod{m}$. \\ + This means that $aa^\star - mk = 1$. \\ + Since $p$ is prime, $\gcd(a, m) = 1$, and $aa^\star - mk = \gcd(a, m)$ \\ + Now use the Extended Euclidean Algorithm from \ref{extend_e_algorithm} to find $a^\star$. + \end{solution} + + \vfill + \pagebreak +\end{document} diff --git a/Advanced/Cryptography/parts/part 3.tex b/Advanced/Cryptography/parts/part 3.tex new file mode 100755 index 0000000..5a8c02f --- /dev/null +++ b/Advanced/Cryptography/parts/part 3.tex @@ -0,0 +1,169 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + \section{Symmetric Cryptosystems} + + \definition{} + The goal of cryptography is to establish private communication between two parties over + a public channel. The rest of this handout tries to achieve this goal, using the tools we've + developed in the last two sections. \\ + + In this handout, a ``symmetric cryptosystem'' consists of the following: + \begin{itemize} + \item[-] A public prime number $p$ (Ideally, a \textit{big} prime number). + \item[-] $k$, a secret key that is shared between both parties. This is NOT public. + \item[-] $E_k(m) = c$, a function that uses key $k$ to encrypt message $m$ into a ciphertext $c$. + \item[-] $D_k(c) = m$, a function that uses key $k$ to decrypt a ciphertext $c$ into message $m$. \\ + \item[-] Of course, $D_k(E_k(m)) = m$. \\ + \end{itemize} + + We have a good reason for picking a prime $p$. A prime base guarantees that every\footnote[1]{except those $\equiv 0 \pmod{p}$, of course} integer has an inverse mod $p$. Review \ref{mod_has_inverse} and convince yourself that this is true. \\ + + \vspace{2ex} + + We'll assume that the secret key $k$ has been shared beforehand. How such a $k$ is created is beyond the scope of this handout, but those that are curious may look up ``Diffie-Hellman Key Exchange'' (Computerphile offers a + pretty good introduction). \\ + + \vspace{2ex} + + One may wonder why we care about secretly exchanging numbers. Those of you with experience in computing may have an answer: any information---text, images, etc---may be represented as a number. For example, we can encode the 26 letters of the alphabet as the numbers $1 - 26$. Such mappings are called ``encodings.'' \\ + + \vspace{2ex} + + Finally, you will notice that the encryption schemes that follow can only take a limited range of inputs. Indeed, even the cyphers in use today have a limited input size. A simple (though possible insecure) way to overcome this limitation is to split the message into ``blocks'' of a desired size, and encrypt each independently. + + + + \vfill + \pagebreak + + \problem{Multiplication mod p} + Consider the cryptosystem where + \begin{itemize} + \item[-] $p$ is a prime (for this problem, fix $p = 11$. Remember, $p$ is public.) + \item[-] $k$ is an integer + \item[-] $E_k(m) = k \times m \pmod{p}$ + \item[-] $D_k(c) = k^\star \times c \pmod{p}$ + \end{itemize} + + + \problempart{} + Encrypt $m = 8$ with $k = 5$. \\ + Decrypt $c = 3$ with $k = 9$. \\ + \textcolor{gray}{In other words, find $E_5(8)$ and $D_9(3)$} + + \begin{solution} + $E_5(8) = 5 \times 8 \equiv 7$ \\ + $D_9(3) = k^\star \times 3 = 5 \times 3 \equiv 4$ + \end{solution} + + \vfill + + \problempart{} + Using this cryptosystem, Nikita sends a message to Sanjit. \\ + Looking over Sanjit's shoulder, you find that $E_k(9) = 8$ \\ + What key was used? \\ + \textcolor{gray}{This is called a \textit{known plaintext attack}. With a good cryptosystem, it will be very difficult to solve this problem.} + + \begin{solution} + $E_k = c = km$ \\ + $E_k \times m^\star = kmm^\star = k$ \\ + + $m^\star = 5; k = 7$ + \end{solution} + + \vfill + + \problempart{} + If you know many ciphertexts encrypted with the same key, can you find the key used to create them? \\ + What range of values can this system effectively encrypt? + Justify all answers. + + \begin{solution} + + If the messages are independent, no. However, analysis is possible if the plaintexts have a known structure. + + \linehack{} + + $m \in \{1, 2, ..., 10\}$ \\ + Note that $m$ cannot be $\equiv 0$. + + \end{solution} + + + \vfill + \pagebreak + + \problem{The Affine Cipher} + Consider the cryptosystem where + \begin{itemize} + \item[-] $p$ is a prime (for this problem, fix $p = 541$) + \item[-] $k = (k_1,\ k_2)$ is a tuple of two integers + \item[-] $E_k(m) = k_1 \times m + k_2 \pmod{p}$ + \item[-] $D_k(c) = k_1^\star \times (c - k_2) \pmod{p}$ + \end{itemize} + + + \problempart{} + Encrypt $m = 204$ with $k = (34,\ 71)$. \\ + Decrypt $c = 431$ with $k = (34,\ 71)$. + + \begin{solution} + $E_k(204) = 34 \times 204 + 71 \equiv 515$ \\ + + $k^\star = 366$ + \hfill\textcolor{gray}{Known from \ref{find_inverse}}\\ + $D_k(431) = 366 (431 - 71) \equiv 297$ + \end{solution} + + \vfill + + \problempart{} + Now, let $p = 601$. You know two plaintext-ciphertext pairs:\\ + $(m_1,\ c_1) = (387,\ 324)$ \\ + $(m_2,\ c_2) = (491,\ 381)$ \\ + How would you find $(k_1, k_2)$? \\ + \textcolor{gray}{\textit{Note: } You do NOT have to find $k$. The calculations take a lot of manual labor. All you need to do is detail the steps you \textit{would} take if you had a calculator.} + + \begin{solution} + $E_k(387) = k_1 \times 387 + k_2 \equiv 324 \pmod{601}$ \\ + $E_k(491) = k_1 \times 491 + k_2 \equiv 381 \pmod{601}$ \\ + + $387k_1 + k_2 - 324 \equiv 491k_1 + k_2 - 381$ \\ + $387k_1 + 57 \equiv 491k_1$ \\ + $104k_1 \equiv 57$ \\ + So $104k_1 + 601a = 57$ \\ + + Solve $104k_1 + 601a = \gcd(601, 104) = 1$, then scale. + \hfill\textcolor{gray}{Remember, 601 is prime.} \\ + $k_1 \equiv -2964 \equiv 41 \pmod{601}$. \\ + + Substitute $k_1 = 41$. \\ + $(k_1, k_2) = (41, 83)$ + + \end{solution} + \vfill + + \problempart{} + If you only know one message and its corresponding ciphertext, can you find the encryption key? \\ + If you know many ciphertexts encrypted with the same key, can you find the key used to create them? \\ + What range of values can this system effectively encrypt? + Justify all answers. + + \begin{solution} + Given $m$ and $c$, you cannot find $k_1$ or $k_2$. + + \linehack{} + + Given any number of ciphertexts, you cannot find $k$. + + \linehack{} + + $m \in \{1, 2, ..., 540\}$ + + Other answers are the same as those to \ref{mult_analysis}. + \end{solution} + + \vfill + \pagebreak +\end{document} diff --git a/Advanced/Lambda Calculus/main.tex b/Advanced/Lambda Calculus/main.tex new file mode 100755 index 0000000..7346b39 --- /dev/null +++ b/Advanced/Lambda Calculus/main.tex @@ -0,0 +1,64 @@ +% https://git.betalupi.com/Mark/latex +% use [nosolutions] flag to hide solutions. +% use [solutions] flag to show solutions. +% Last built with version 1.1.0 + +\documentclass[ + solutions, + singlenumbering +]{ormc_handout} + +\usepackage{url} +\usepackage{mathtools} % for \coloneqq +\usepackage{subfiles} + +% 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} + +% Notice that I a b = 1 a b! + + +\begin{document} + + \maketitle + + + {Lambda Calculus} + { + Prepared by Mark on \today + } + + + \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 + + + \subfile{parts/00 intro} + \subfile{parts/01 combinators} + \subfile{parts/02 boolean} + \subfile{parts/03 numbers} + \subfile{parts/04 recursion} + \subfile{parts/05 challenges} + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/00 intro.tex b/Advanced/Lambda Calculus/parts/00 intro.tex new file mode 100755 index 0000000..943d763 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/00 intro.tex @@ -0,0 +1,254 @@ +\documentclass[../main.tex]{subfiles} + + +\begin{document} + + \section{Definitions} + + \generic{$\lm$ Notation:} + $\lm$ notation is used to define functions, and looks like $(\lm ~ \text{input} ~ . ~ \text{output})$. \\ + Consider the following statement: + $$ + I = \lm a . a + $$ + + This tells us that $I$ is a function that takes its input, $a$, to itself. We'll call this the \textit{identity function}. \\ + + To apply functions, put them next to their inputs. We'll omit the usual parentheses to save space. + + $$ + I ~ \star = (\lm a . a) ~ \star = \star + $$ + + $$ + (M~\star) = + (\lm \tzm{b}a. a)~\tzmr{a}\star = + \star + \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} + $$ + + Functions are left-associative: If $A$ and $B$ are functions, $(A~B~\star)$ is equivalent to $((A~B)~\star)$. As usual, we'll use parentheses to group terms if we want to override this order: $(A~(B~\star)) \neq (A~B~\star)$ \\ + In this handout, all types of parentheses ( $(), [],$ etc ) are equivalent. + + \vfill + + \generic{$\beta$-Reduction:} + + $\beta$-reduction is a fancy name for \say{simplifying an expression.} We've already done it once above. + + Let's make another function: + $$ + M = \lm f . f f + $$ + $M$ takes a function as an input and calls it on itself. What is $(M~I)$? + $$ + (M~I) = + ((\lm \tzm{b}f.f f)~\tzmr{a}I) = + (I~I) = + ((\lm \tzm{d}a.a)~\tzmr{c}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); + \draw[->,gray,shorten >=5pt,shorten <=3pt] + (c.center) to (d.center); + \end{tikzpicture} + $$ + + We cannot reduce this any further, so we stop. Our expression is now in \textit{$\beta$-normal form}. + + \vfill + \pagebreak + + \problem{} + Reduce the following expressions: + \begin{itemize} + \item $I~I$ + \item $I~I~I$ + \item $(\lm a .(a~a~a)) ~ I$ + \item $(\lm a . (\lm b . a)) ~ M ~ I$ + \end{itemize} + + \vfill + \pagebreak + + \generic{Currying:} + + Lambda functions are only allowed to take one argument, but we can emulate multivariable functions through \say{currying.} + + \vspace{1ex} + + Before we begin, let's review \textit{function composition}. With \say{normal} functions, composition is written as $(f \circ g)(x) = f(g(x))$. This means \say{$f$ of $g$ of $x$}. + + \vspace{1ex} + + To demonstrate currying, we'll make a function $C$ in lambda calculus, which takes two functions ($f$ and $g$), an input $x$, and produces $f$ applied to $g$ applied to $x$. \\ + + In other words, we want a $C$ so that $C~f~g~x = f~(g~x)$ + + \vspace{1ex} + + We'll define this $C$ as follows: + $$ + C = \lm f . (\lm g . (\lm x . f(g(x)))) + $$ + + \vspace{1ex} + + This looks awfully scary, so let's take this expression apart. \\ + C is a function that takes one argument ($f$) and returns a function (underlined): + $$ + C = \lm f .(~~\tzm{a} \lm g . (\lm x . f(g(x))) \tzm{b}~~) + \begin{tikzpicture}[ + overlay, + remember picture + ] + \node[below = 1ex] at (a.center) (aa) {}; + \node[below = 1ex] at (b.center) (bb) {}; + + \path[draw = gray] (aa) to (bb); + \end{tikzpicture} + $$ + + \vspace{1ex} + + The function it returns does the same thing. It takes an argument $g$, and returns \textit{another} function: + $$ + C = \lm f . (~~ \lm g . (~~\tzm{a} \lm x . f(g(x)) \tzm{b}~~) ~~) + \begin{tikzpicture}[ + overlay, + remember picture + ] + \node[below = 1ex] at (a.center) (aa) {}; + \node[below = 1ex] at (b.center) (bb) {}; + + \path[draw = gray] (aa) to (bb); + \end{tikzpicture} + $$ + + \vspace{1ex} + + This last function $\lm x. f(g(x))$ takes one argument, and returns $f(g(x))$. Since this function is inside the previous two, it has access to their arguments, $f$ and $g$. + + \vspace{2ex} + + So, currying allows us to create multivariable functions by nesting single-variable functions. \\ + As you saw above, such 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, + $$ + C = \lm f . (\lm g . (\lm x . f(g(x)))) + $$ + will become + $$ + C = \lm fgx.(~f(g(x))~) + $$ + + \vspace{1ex} + + This is only notation. \textbf{Curried functions are not multivariable functions!} They must be evaluated one variable at a time, just like their un-curried version. Substituting all curried variables in one go may cause errors, as you'll see below. + + \problem{} + Evaluate $C~M~I~\star$ \\ + Then, evaluate $C~I~M~I$ \\ + \hint{Place parentheses first. Remember, function application is left-associative.} + + + \vfill + \pagebreak + + + \definition{$\alpha$-equivalence} + We say two functions are \textit{$\alpha$-equivalent} if they differ only by the names of their variables: + $I = \lm a.a = \lm b.b = \lm \heartsuit . \heartsuit = ...$ + + \generic{$\alpha$-Conversion:} + + Variables inside functions are \say{scoped.} We must take care to keep separate variable separate. + + For example, take the functions \\ + $A = \lm a b . a$ \\ + $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. + + \vspace{2ex} + + Notice that both $A$ and $B$ use the input $b$. However, each $b$ is \say{bound} to a different function. The two $b$s are therefore distinct. + + \vspace{2ex} + + Let's rewrite $B$ as $\lm c . c$ and try again: + + $$ + (A~B) = \lm b . ( \lm c . c) = \lm bc . c + $$ + + Now, we correctly find that $(A~B~I) = (\lm bc . c)~I = \lm c . c = B = I$. + + \problem{} + Let $C = \lm abc.b$ \\ + Reduce $(C~a~c~b)$. + + \begin{solution} + I'll rewrite $(C~a~c~b)$ as $(C~a_1~c_1~b_1)$: + \begin{align*} + C = (\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 + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/01 combinators.tex b/Advanced/Lambda Calculus/parts/01 combinators.tex new file mode 100755 index 0000000..7d67440 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/01 combinators.tex @@ -0,0 +1,47 @@ +\documentclass[../main.tex]{subfiles} + + +\begin{document} + + \section{Combinators} + + \definition{} + A \textit{free variable} in a $\lm$-expression is a variable that isn't bound to any input. \\ + For example, $b$ is a free variable in $\lm a. b$. The same is true of $\star$ in any of the previous pages. + + A \textit{combinator} is a function with no free variables. + + \definition{The Kestrel} + + Notable combinators are often named after birds.\hspace{-0.5ex}\footnotemark{} We've already met a few: \\ + The \textit{Idiot}, $I = \lm a.a$ \\ + The \textit{Mockingbird}, $M = \lm f.ff$ \\ + The \textit{Cardinal}, $C = \lm fgx.(~ f(g(x)) ~)$ \\ + + \footnotetext{Raymond Smullyan's \textit{To Mock a Mockingbird} is responsible for this.} + + \vspace{2ex} + + Another notable combinator is $K$, the \textit{Kestrel}: + $$ + K = \lm ab . a + $$ + \problem{} + What does the Kestrel do? Explain in plain English. \\ + \hint{What is $(K~\heartsuit~\star)$?} + + \vspace{2cm} + + \problem{} + Reduce $(K~I)$ to derive the \textit{Kite}. How does the Kite compare to the Kestrel? \\ + We'll call the Kite KI. + + \begin{solution} + $\text{KI} = \lm ab . b$. \\ + \end{solution} + + \vfill + \pagebreak + + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/02 boolean.tex b/Advanced/Lambda Calculus/parts/02 boolean.tex new file mode 100755 index 0000000..33e2ee6 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/02 boolean.tex @@ -0,0 +1,71 @@ +\documentclass[../main.tex]{subfiles} + + +\begin{document} + + \section{Boolean Algebra} + + The Kestrel selects its first argument, and the Kite selects its second. This \say{choosing} behavior is awfully similar to something you may have already seen... + + \vspace{1ex} + + Let $T = K\phantom{I} = \lm ab . a$ \\ + Let $F = KI = \lm ab . b$ \\ + + \problem{} + Write a function $\text{NOT}$ so that $(\text{NOT} ~ T) = F$ and $(\text{NOT}~F) = T$. \\ + \hint{What is $(T~\heartsuit~\star)$? How about $(F~\heartsuit~\star)$?} + + + \begin{solution} + $\text{NOT} = \lm a . (a~F~T)$ \\ + \end{solution} + + \vfill + + \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, but make sure the kids understand how the solutions below work. + \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*} + + It may be worth mentioning that OR $= \lm ab.(M~a~b)$ is also a solution. + \end{solution} + + \problem{} + To complete our boolean algebra, write the boolean equality check EQ. \\ + 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 + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/03 numbers.tex b/Advanced/Lambda Calculus/parts/03 numbers.tex new file mode 100755 index 0000000..c16e2a3 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/03 numbers.tex @@ -0,0 +1,226 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + + \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}. \\ + 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 $\alpha$-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: \\ + $1 = \lm fa . (f~a)$. + + \vspace{1ex} + + Naturally, \\ + $2 = \lm fa . [~f~(f~a)~]$ \\ + $3 = \lm fa . [~f~(f~(f~a))~]$ + + \vspace{1ex} + + The round parentheses are \textit{essential}. Our lambda calculus is left-associative! + + \vspace{2ex} + + Also, notice that $1$ is very similar to $I$: + $$ + I~\heartsuit~\star = 1~\heartsuit~\star + $$ + + Zero is false, and one is the identity. Isn't that wonderful? + \end{solution} + + \vfill + + \problem{} + What is $(4~I)~\star$? + + \vfill + + \problem{} + What is $(3~NOT~T)$? \\ + How about $(8~NOT~F)$? + + \vfill + + \pagebreak + + \problem{} + This handout may remind you of Professor Oleg's handout on Peano's axioms. Good. \\ + While you're there, recall the tools we used to build the natural numbers: \\ + We had a zero element and a \say{successor} operation so that $1 \coloneqq S(0)$, $2 \coloneqq S(1)$, and so on. + + \vspace{1ex} + + Create a successor operation for the Church numerals. \\ + \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. \\ + 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{} + Adding is nice, but we can do better. \\ + Design a function MULT that multiplies two numbers. \\ + \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. \\ + $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]$\\ + $NZ = \lm n .[n~(\lm a.T)~F]$ + \end{solution} + + \vfill + + \problem{} + Data structures will be useful. Design an expression PAIR that constructs two-value tuples. \\ + For example, say $A = \text{PAIR}~1~2$. Then, \\ + $(A~T)$ should reduce to $1$ \\ + $(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$. \\ + Like currying, this is only notation. The underlying $\lm$ logic remains the same. + + \pagebreak + + \problem{} + Write a function $H$, which we'll call \say{shift and add.} \\ + It does exactly what it says on the tin: \\ + + \vspace{1ex} + + Given an input pair, it should shift its right argument left, then add one. \\ + $H~\langle 0, 1 \rangle$ should reduce to $\langle 1, 2\rangle$ \\ + $H~\langle 1, 2 \rangle$ should reduce to $\langle 2, 3\rangle$ \\ + $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{} + Design a function $D$ that un-does $S$. That means \\ + $D(1) = 0$, $D(2) = 1$, etc. $D(0)$ should be zero. \\ + \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} + + \begin{solution} + Here's a different solution. \\ + Can you figure out how it works? \\ + + \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 + \pagebreak + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/04 recursion.tex b/Advanced/Lambda Calculus/parts/04 recursion.tex new file mode 100755 index 0000000..a1d7f76 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/04 recursion.tex @@ -0,0 +1,67 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + + \section{Recursion} + + 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 notation. Functions in lambda calculus are \textit{anonymous}, which means we can't call them before they've been fully defined. + + \vspace{1ex} + + As an example, consider the statement $A = \lm a. A~a$ \\ + This means \say{write $(\lm a.A~a)$ whenever you see $A$.} However, $A$ is \textit{inside} what we're rewriting. We'd fall into infinite recursion before even starting our $\beta$-reduction! + + \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. \\ + \note{Your answer should be short and sweet.} + + \vspace{1ex} + + This expression is often called $\Omega$, after the last letter of the Greek alphabet. \\ + $\Omega$ useless on its own, but gives us a starting point for recursion. + + \begin{solution} + $\Omega = M~M = (\lm x . xx) (\lm x . xx)$ + + \vspace{1ex} + + An uninspired mathematician might call the Mockingbird $\omega$, \say{little omega}. \\ + \end{solution} + + \vfill + + \definition{} + This is the \textit{Y-combinator}, easily the most famous $\lm$ expression. \\ + 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? \\ + Evaluate $Y f$. + + \vfill + \pagebreak + +\end{document} \ No newline at end of file diff --git a/Advanced/Lambda Calculus/parts/05 challenges.tex b/Advanced/Lambda Calculus/parts/05 challenges.tex new file mode 100755 index 0000000..1b8d941 --- /dev/null +++ b/Advanced/Lambda Calculus/parts/05 challenges.tex @@ -0,0 +1,87 @@ +\documentclass[../main.tex]{subfiles} + +\begin{document} + + \section{Challenges} + + Do \ref{Yfac} first, then finish the rest in any order. \\ + Have fun! + + \problem{} + Design a recursive factorial function using $Y$. \\ + + \vfill + + \problem{} + Design a non-recursive factorial function. \\ + \note{This one is a lot easier than \ref{Yfac}, but I don't think it will help you solve it.} + + \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}. \\ + Lists have a defined length, so you should be able to tell when you're on the last element. + + \problem{} + Write POW $a$ $b$, which raises $b$ to the $a$th power. + + \problem{} + Write a MOD $a$ $b$ function that reduces to the remainder of $a \div b$. + + \begin{solution} + \textbf{Factorial with recursion:} + \vspace{3ex} + + $\text{FAC} = \lm yn.[Z~n][1][\text{MULT}~n~(y~(\text{D}~n))]$ + + \linehack{} + + \textbf{Factorial without recursion:} + \vspace{3ex} + + $\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) + $ + + \linehack{} + + \textbf{Lists:} + \vspace{3ex} + + 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. \\ + \say{item} is the thing you're storing \\ + \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 ANY function 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 + + \problem{Bonus} + Play with \textit{Lamb}, an automatic lambda expression evaluator. \\ + \url{https://git.betalupi.com/Mark/lamb} +\end{document} \ No newline at end of file