# the church encoding for booleans true = \t f. t; false = \t f. f; if = \b x y. b x y; not = \x. if x false true; and = \x y. if x y false; or = \x y. if x true y; xor = \x y. if x (not y) y; # the church encoding for peano numbers zero = \f x. x; succ = \n f x. f (n f x); pred = \n f x. n (\g h. h (g f)) (\u. x) (\u. u); # addition, subtraction and multiplication plus = \m n f x. m f (n f x); sub = \m n. (n pred) m; mul = \m n f. m (n f); # some useful predicates on church numerals even = \n. n not true; iszero = \m. m (\x. false) true; lte = \m n. iszero (sub m n); gte = \m n. iszero (sub n m); eq = \m n. and (lte m n) (gte m n); lt = \m n. and (lte m n) (not (gte m n)); gt = \m n. and (gte m n) (not (lte m n)); # aliases for the church numerals up to ten one = succ zero; two = succ one; three = succ two; four = succ three; five = succ four; six = succ five; seven = succ six; eight = succ seven; nine = succ eight; ten = succ nine; # integer exponentation pow = \m n. n (\x. mul m x) one; # Turner's combinators I = \x .x; K = \x y. x; S = \f g x. (f x) (g x); W = \f x. f x x; B = \f g x. f (g x); C = \f x y. f x y; # the fixpoint combinator Y = \f. (\x. f (x x)) \x. f (x x); # a divergent labmda term omega = (\x. x x) \x. x x; # factorial fac = Y (\facF n. if (iszero n) one (mul n (facF (pred n)))); # the church encoding for pairs pair = \x y f. f x y; fst = \p. p (\x y. x); snd = \p. p (\x y. y); # now, encode ADTs match = \x pats. x (\n f. f (fst ((n snd) pats))); # the ADT representation of lists nil = \ w. w zero (\f. f); cons = \h t w. w one (\f. f h t); # head and tail, by pattern matching head = \l. match l (pair nil (pair (\h t. h) zero)); tail = \l. match l (pair nil (pair (\h t. t) zero)); # the ith element of a list index = \n l. head (n tail l); # right fold on a list foldr = \f z. Y (\foldF l. match l (pair z (pair (\h t. f h (foldF t)) zero))); # left fold on a list foldl = \f. Y (\foldF r l. match l (pair r (pair (\h t. foldF (f r h) t) zero))); # the length of a list len = foldl (\x h. succ x) zero; # the mapping function on a list map = \f. Y (\mapF l. match l (pair nil (pair (\h t. cons (f h) (mapF t)) zero))); # list generator unfold = \g until. Y (\unfoldF x. if (until x) (cons x nil) (cons x (unfoldF (g x)))); # some other interesting list functions.... iterate = \g. unfold g (K false); nats = iterate succ zero; upTo = \n. unfold succ (\x. gte x n) zero; zipWith = \f. Y (\zipF l1 l2. match l1 (pair nil (pair (\h1 t1. match l2 (pair nil (pair (\h2 t2. cons (f h1 h2) (zipF t1 t2)) zero))) zero))); zip = zipWith pair; take = \n l. zipWith K l (tail (upTo n)); drop = \n l. n tail l; minAux = foldl (\x y. if (lt y x) y x); min = \l. match l (pair nil (pair minAux zero)); maxAux = foldl (\x y. if (gt y x) y x); max = \l. match l (pair nil (pair maxAux zero)); remove = \x. Y (\removeF l. match l (pair nil (pair (\h t. if (eq h x) t (cons h (removeF t))) zero))); insertSort = Y (\sortF l. match l (pair nil (pair (\h t. (\x. cons x (sortF (remove x l))) (minAux h t)) zero)));