Chapter 2: Data Abstraction
Since lambda calculus is a programming language, the machinery to encode data structures is necessary.
Another core idea about lambda calculus is that everything is function. Don't be surprised, just continue and see.
Booleans and If Function
Let's start with simplest ones - booleans. true is defined as a function that selects its first parameter and false selects its second one.
Owing to the selection design of booleans, it is natural to implement if function like this:
You may verify following expressions:
But as you apply reduction to if function, you will find out it is entirely redundant, since booleans are already selector themselves.
Logic Functions
Making good use of selection semantics contributes to the establishment of fundamental logic functions.
You may combine basic logic functions above and perform certain reductions to obtain more, or directly construct one according to your innermost intuition.
Ordered Pairs
Mathematicians love ordered pairs. They may be the infrastructure of all data structures. For example, tuples are often defined as recursive ordered pairs. Ordered pairs in lambda calculus are defined as follows:
constructs an ordered pair, and retrieve the first and second element of the ordered pair respectively.
Note: symbol is homophonic with "pair" and alphabetic names originated from Lisp.
Unlike previous functions, I didn't uncurry all parameters because the element selector seldom comes together with the pair elements. With delayed accessors, it creates a semantics as if the elements are "stored" in the function returned by .
Triples
As long as oredered pairs are ready, other abstract data types could be implemented. For example, a triple may be defined as:
Note: symbol is homophonic with "triple"
Tuples of arbitrary length could be implemented in the same approach.
Linear Lists
Tuples are not enough, an extensible linear list is expected. So there is.
Unlike tuples, the second element of last pair of a list should not store a regular value but a special object that indicates the end of the list. It must be intrinsic and unable to be implemented via lambda calculus to avoid potential conflicts with other regular logics. Let's call the indicator . The predicate to test if an object is is .
Then a prepending singly linked list is done!
Now is , or just for short.
Recursive definition of lists provokes recursive algorithm. But recursion will not be discussed until Chapter 5. At the same time you will see the functionality of .
Linear data structures are merely pieces of cake if you keep exploring.
Trees
What about trees?
Remember triples? It's high time to reuse it to build a binary tree.
Did I define anything new? Yes and no. Yes semantically, no underlyingly. That's why we call them abstract data types. Abstraction rocks!
Data Abstraction
In fact, by defining appropriate accessor functions, any abstract data type is available from ordered pairs. Differences are no more than how pairs are organized and how pairs are manipulated. Underlying representation of pairs remains unchanged.
See Structure and Interpretation of Computer Programs for more about data abstraction.