Lambda Calculus Implementation in Python

Table of Contents

Introduction

This org-mode file contains a Lambda Calculus implementation in Python. Each section includes self-contained code blocks that can be run independently.

Lambda Expressions

# Step 1: Understand Lambda Expressions
identity = lambda x: x
print(identity(5))  # Output: 5

Church Booleans

# Step 2: Implement Church Booleans
lc_true = lambda x: lambda y: x
lc_false = lambda x: lambda y: y
lc_if = lambda condition: lambda then: lambda else_: condition(then)(else_)

print(lc_if(lc_true)("yes")("no"))  # Output: yes

Basic Combinators

# Step 3: Implement Basic Combinators
I = lambda x: x
K = lambda x: lambda y: x
KI = lambda x: lambda y: y

print(I(5))  # Output: 5
print(K(3)(4))  # Output: 3
print(KI(3)(4))  # Output: 4

Church Numerals

# Step 4: Create Church Numerals
lc_zero = lambda f: lambda x: x
lc_succ = lambda n: lambda f: lambda x: f(n(f)(x))

def church_to_int(n):
    return n(lambda x: x + 1)(0)

lc_one = lc_succ(lc_zero)
lc_two = lc_succ(lc_one)

print(church_to_int(lc_zero))  # Output: 0
print(church_to_int(lc_one))   # Output: 1
print(church_to_int(lc_two))   # Output: 2

Basic Arithmetic

# Step 5: Implement Basic Arithmetic
lc_zero = lambda f: lambda x: x
lc_succ = lambda n: lambda f: lambda x: f(n(f)(x))

def church_to_int(n):
    return n(lambda x: x + 1)(0)

lc_add = lambda m: lambda n: lambda f: lambda x: m(f)(n(f)(x))
lc_mult = lambda m: lambda n: lambda f: m(n(f))

lc_one = lc_succ(lc_zero)
lc_two = lc_succ(lc_one)
lc_three = lc_succ(lc_two)

print(church_to_int(lc_add(lc_one)(lc_two)))    # Output: 3
print(church_to_int(lc_mult(lc_two)(lc_three))) # Output: 6

Pairs

# Step 6: Implement Pairs
lc_pair = lambda x: lambda y: lambda f: f(x)(y)
lc_first = lambda p: p(lambda x: lambda y: x)
lc_second = lambda p: p(lambda x: lambda y: y)

my_pair = lc_pair(3)(4)
print(lc_first(my_pair))   # Output: 3
print(lc_second(my_pair))  # Output: 4

Lists

# Step 7: Build Lists Using Pairs
lc_true = lambda x: lambda y: x
lc_false = lambda x: lambda y: y
lc_pair = lambda x: lambda y: lambda f: f(x)(y)
lc_first = lambda p: p(lambda x: lambda y: x)
lc_second = lambda p: p(lambda x: lambda y: y)

lc_nil = lambda x: lc_true
lc_cons = lc_pair
lc_is_nil = lambda l: l(lambda h: lambda t: lc_false)
lc_head = lc_first
lc_tail = lc_second

# Helper function to convert Python list to Church-encoded list
def list_to_church(lst):
    if not lst:
        return lc_nil
    return lc_cons(lst[0])(list_to_church(lst[1:]))

# Helper function to convert Church-encoded list to Python list
def church_to_list(l):
    result = []
    while not lc_is_nil(l)(True):
        result.append(lc_head(l))
        l = lc_tail(l)
    return result

my_list = list_to_church([1, 2, 3])
print(church_to_list(my_list))  # Output: [1, 2, 3]
print(lc_head(my_list))         # Output: 1
print(church_to_list(lc_tail(my_list)))  # Output: [2, 3]
print(lc_is_nil(my_list)(True)(False))   # Output: False
print(lc_is_nil(lc_nil)(True)(False))    # Output: True

Comparison Operations

# Step 8: Implement Comparison Operations
lc_zero = lambda f: lambda x: x
lc_succ = lambda n: lambda f: lambda x: f(n(f)(x))
lc_true = lambda x: lambda y: x
lc_false = lambda x: lambda y: y

lc_is_zero = lambda n: n(lambda x: lc_false)(lc_true)
lc_leq = lambda m: lambda n: lc_is_zero(lc_sub(m)(n))
lc_eq = lambda m: lambda n: lc_and(lc_leq(m)(n))(lc_leq(n)(m))

lc_and = lambda x: lambda y: x(y)(lc_false)
lc_sub = lambda m: lambda n: n(lambda n: lambda f: lambda x: n(
    lambda g: lambda h: h(g(f)))(lambda y: x)(lambda y: y))(m)

lc_one = lc_succ(lc_zero)
lc_two = lc_succ(lc_one)

print(lc_is_zero(lc_zero)(True)(False))  # Output: True
print(lc_is_zero(lc_one)(True)(False))   # Output: False
print(lc_leq(lc_one)(lc_two)(True)(False))  # Output: True
print(lc_eq(lc_one)(lc_one)(True)(False))   # Output: True
print(lc_eq(lc_one)(lc_two)(True)(False))   # Output: False

Higher-Order List Operations

# Step 9: Implement Higher-Order List Operations
lc_zero = lambda f: lambda x: x
lc_succ = lambda n: lambda f: lambda x: f(n(f)(x))
lc_true = lambda x: lambda y: x
lc_false = lambda x: lambda y: y
lc_pair = lambda x: lambda y: lambda f: f(x)(y)
lc_first = lambda p: p(lambda x: lambda y: x)
lc_second = lambda p: p(lambda x: lambda y: y)
lc_nil = lambda x: lc_true
lc_cons = lc_pair
lc_is_nil = lambda l: l(lambda h: lambda t: lc_false)
lc_head = lc_first
lc_tail = lc_second

lc_if = lambda condition: lambda then: lambda else_: condition(then)(else_)

lc_map = lambda f: lambda l: lc_if(lc_is_nil(l))(lc_nil)(lambda: lc_cons(
    f(lc_head(l)))(lc_map(f)(lc_tail(l))))()
lc_filter = lambda p: lambda l: lc_if(lc_is_nil(l))(lc_nil)(lambda: lc_if(
    p(lc_head(l)))(lambda: lc_cons(lc_head(l))
                   (lc_filter(p)(lc_tail(l))))(lambda: lc_filter(p)
                                               (lc_tail(l))))()
lc_fold = lambda f: lambda acc: lambda l: lc_if(lc_is_nil(l))(acc)(
    lambda: lc_fold(f)(f(acc)(lc_head(l)))(lc_tail(l)))()

def list_to_church(lst):
    if not lst:
        return lc_nil
    return lc_cons(lst[0])(list_to_church(lst[1:]))

def church_to_list(l):
    result = []
    while not lc_is_nil(l)(True):
        result.append(lc_head(l))
        l = lc_tail(l)
    return result

my_list = list_to_church([1, 2, 3])

doubled_list = lc_map(lambda x: x * 2)(my_list)
print("Doubled list:", church_to_list(doubled_list))

filtered_list = lc_filter(lambda x: x > 1)(my_list)
print("Filtered list:", church_to_list(filtered_list))

sum_list = lc_fold(lambda x: lambda y: x + y)(0)(my_list)
print("Sum of list:", sum_list)

Recursion and Fixed-Point Combinators

# Step 10: Explore Recursion and Fixed-Point Combinators
lc_zero = lambda f: lambda x: x
lc_succ = lambda n: lambda f: lambda x: f(n(f)(x))
lc_true = lambda x: lambda y: x
lc_false = lambda x: lambda y: y
lc_if = lambda condition: lambda then: lambda else_: condition(then)(else_)

lc_is_zero = lambda n: n(lambda x: lc_false)(lc_true)
lc_sub = lambda m: lambda n: n(lambda n: lambda f: lambda x: n(
    lambda g: lambda h: h(g(f)))(lambda y: x)(lambda y: y))(m)
lc_mult = lambda m: lambda n: lambda f: m(n(f))

def church_to_int(n):
    return n(lambda x: x + 1)(0)

lc_one = lc_succ(lc_zero)

Y = lambda f: (lambda x: f(lambda y: x(x)(y)))(lambda x: f(lambda y: x(x)(y)))

factorial = Y(lambda f: lambda n: lc_if(lc_is_zero(n))(lc_one)
              (lambda: lc_mult(n)(f(lc_sub(n)(lc_one))))())

lc_five = lc_succ(lc_succ(lc_succ(lc_succ(lc_one))))
print("Factorial of 5:", church_to_int(factorial(lc_five)))

Conclusion

This org-mode file provides a comprehensive implementation of Lambda Calculus in Python, including Church encodings for booleans, numerals, and lists, as well as higher-order functions and recursion using the Y combinator. Each section can be run independently to explore different aspects of Lambda Calculus.

Author: Claude 3.5 Sonnet (Anthropic, PBC)

jwalsh@nexus

Last Updated: 2025-07-30 13:45:27

build: 2025-12-23 09:12 | sha: e32f33e