Church encodings

Table of Contents

1. Review

We looked at Church encodings of four different data types:

  • Booleans
  • Natural numbers
  • Pairs
  • Lists

1.1. Booleans

Booleans can be one of two values, \(๐•‹\) and \(๐”ฝ\). In Haskell, they are represented by the algebraic data type Bool:

data Bool = True | False

In ฮป-calculus we can represent them as two ฮป-terms: \[๐•‹ โ‰ ฮปx, y.x\] \[๐”ฝ โ‰ ฮปx, y.y\] Defining Booleans this way allows us to define fun operations on Booleans, such as: \[\mathtt{ifThenElse} โ‰ ฮปp, x, y.p\,x\,y\] \[\mathtt{not} โ‰ ฮปp.p\,๐”ฝ\,๐•‹\] \[\mathtt{and} โ‰ ฮปp, q.p\,q\,๐”ฝ\] \[\mathtt{or} โ‰ ฮปp, q.p\,๐•‹\,q\]

1.2. Natural numbers

The natural numbers 0, 1, 2, etc., can be encoded in Haskell by the algebraic data type Nat:

data Nat = Zero | Succ Nat

In ฮป-calculus we can represent them by using the following translation (\(โŒœยทโŒ\)): \[โŒœ0โŒ โ‰ ฮปs, z.z\] \[โŒœ\mathtt{Succ}\,nโŒ โ‰ ฮปs, z.s\,(โŒœnโŒ\,s\,z)\] For example, \(1\) (i.e., \(\mathtt{Succ}\,0\)) would receive the translation \(โŒœ\mathtt{Succ}\,0โŒ = ฮปs, z.s\,(โŒœ0โŒ\,s\,z) = ฮปs, z.s\,((ฮปs, z.z)\,s\,z) โ†’_ฮฒ^* ฮปs, z.s\,(s\,z)\). In general, the number of occurrences of the variable bound by the outer abstraction in the encoding of a natural number is just that number.

We can now define functions on natural numbers, such as \[\mathtt{succ} โ‰ ฮปn, s, z.s\,(n\,s\,z)\] i.e., the successor function, which, given a natural number, takes its successor. Other useful operations are \[\mathtt{plus} โ‰ ฮปm, n.m\,\mathtt{succ}\,n\] which takes the successor of \(n\) \(m\) times, and \[\mathtt{mult} โ‰ ฮปm, n.m\,(\mathtt{plus}\,n)\,โŒœ0โŒ\] which adds \(n\) to \(0\) \(m\) times.

1.3. Pairing

Taking a pair of two values can be done as follows: \[โŒœโŸจa, bโŸฉโŒ โ‰ ฮปf.f\,โŒœaโŒ\,โŒœbโŒ\] Given this encoding of pairing, we may define the following two projection functions, which take the first and second projections of a pair, respectively: \[ฯ€โ‚ โ‰ ฮปp.p\,๐•‹\] \[ฯ€โ‚‚ โ‰ ฮปp.p\,๐”ฝ\] In Haskell, these functions correspond to the functions

fst :: (a, b) -> a
snd :: (a, b) -> b

which give back the first and second projections of a pair, respectively.

1.4. Lists

Finally, lists! In Haskell, these are encoded as an algebraic data type (equivalent to)

data List a = Empty | Cons a (List a)

In the ฮป-calculus, we may define them as using the translation \[โŒœ[]โŒ โ‰ ฮปc, n.n\] \[โŒœa : lโŒ โ‰ ฮปc, n.c\,โŒœaโŒ\,(โŒœlโŒ\,c\,n)\] For example, the the list \([1]\) would be translated as \(โŒœ[1]โŒ = ฮปc, n.c\,โŒœ1โŒ(โŒœ[]โŒ\,c\,n) = ฮปc, n.c\,โŒœ1โŒ\,((ฮปc, n.n)\,c\,n) โ†’_ฮฒ^* ฮปc, n.c\,โŒœ1โŒ\,n\).

We can now, e.g., take the length of a list in terms of a function \[\mathtt{length} โ‰ ฮปl.l\,(ฮปx.\mathtt{succ})\,โŒœ0โŒ\] and we can, e.g., take the head (i.e., first element) of a list using a function \[\mathtt{head} โ‰ ฮปl.l\,๐•‹\,๐”ฝ\] Note that, if passed the empty list, \(\mathtt{head}\) just gives back \(๐”ฝ\).

2. Exercises

2.1. Part 1

Compute \(\mathtt{plus}\,โŒœ2โŒ\,โŒœ3โŒ\).

2.2. Part 2

Define a function \(\mathtt{ifThen}\) which takes two truth values and gives back \(๐•‹\) if the first truth value is \(๐”ฝ\) or the second truth value is \(๐•‹\) (or if both the first is \(๐”ฝ\) and the second is \(๐•‹\)). Do this without using either \(\mathtt{not}\) or \(\mathtt{or}\) in your definition!

2.3. Part 3

Define a function \(\mathtt{append}\) which takes two lists and appends them. That is, \(\mathtt{append}\) should have the following behavior: \[\mathtt{append}\,โŒœ[]โŒ\,l โ‰ก_ฮฒ l\] \[\mathtt{append}\,โŒœa : lโ‚โŒ\,lโ‚‚ โ‰ก_ฮฒ ฮปc, n.c\,โŒœaโŒ\,(\mathtt{append}\,lโ‚\,lโ‚‚)\]

2.4. Part 4

Define a function \(\mathtt{all}\) which, given a list of Booleans (i.e., either \(๐•‹\) or \(๐”ฝ\)), returns \(๐•‹\) if all of them are \(๐•‹\) and returns \(๐”ฝ\) otherwise.

2.5. Part 5

Define a function \(\mathtt{any}\) which, given a list of Booleans (i.e., either \(๐•‹\) or \(๐”ฝ\)), returns \(๐•‹\) if any of them is \(๐•‹\) and returns \(๐”ฝ\) otherwise.

2.6. Part 6

Define a function \(\mathtt{sum}\) which, given a list of natural numbers, returns their sum.

2.7. Part 7

Define a function \(\mathtt{map}\) which, given a function \(f\) from \(a\)'s to \(b\)'s, applies \(f\) to each member of a list of \(a\)'s to get back a list of \(b\)'s. That is, \(\mathtt{map}\) should have the following behavior: \[\mathtt{map}\,f\,โŒœ[]โŒ โ‰ก_ฮฒ โŒœ[]โŒ\] \[\mathtt{map}\,f\,โŒœa : lโŒ โ‰ก_ฮฒ ฮปc, n.c\,(f\,โŒœaโŒ)\,(\mathtt{map}\,f\,โŒœlโŒ\,c\,n)\]

2.8. Part 8

Define a function \(\mathtt{filter}\) which, given a function \(f\) from \(a\)'s to Booleans and a list of \(a\)'s, filters the list using \(f\). That is, it returns a new list of \(a\)'s such that \(x\) is on the new list just in case \(x\) was on the old list and \(f x โ†’_ฮฒ^* ๐•‹\). In other words, \(\mathtt{filter}\) should satisfy the following equivalences: \[\mathtt{filter}\,f\,โŒœ[]โŒ โ‰ก_ฮฒ โŒœ[]โŒ\] \[\mathtt{filter}\,f\,โŒœa : lโŒ โ‰ก_ฮฒ ฮปc, n.c\,โŒœaโŒ\,(\mathtt{filter}\,f\,โŒœlโŒ\,c\,n)\,\,\,\,\,\,\,\,\,\,\,\,\text{(if }f\,โŒœaโŒ โ†’_ฮฒ^* ๐•‹\text{)}\] \[\mathtt{filter}\,f\,โŒœa : lโŒ โ‰ก_ฮฒ \mathtt{filter}\,f\,โŒœlโŒ\,\,\,\,\,\,\,\,\,\,\,\,\text{(if }f\,โŒœaโŒ โ†’_ฮฒ^* ๐”ฝ\text{)}\]

Author: Julian Grove

Created: 2023-09-24 Sun 00:46

Validate