Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Church encoding

From Wikipedia, the free encyclopedia
Representation of natural numbers and other data types in lambda calculus

Inmathematics,Church encoding is a way of representing various data types in thelambda calculus.

In the untyped lambda calculus the only primitive data type are functions, represented by lambda abstraction terms. Types that are usually considered primitive in other notations (such as integers, Booleans, pairs, lists, and tagged unions) are not natively present.

Hence the need arises to have ways to represent the data of these varying types by lambda terms, that is, byfunctions that are taking functions as their arguments and are returning functions as their results.

TheChurch numerals are a representation of the natural numbers using lambda notation. The method is named forAlonzo Church, who first encoded data in the lambda calculus this way. It can also be extended to represent other data types in the similar spirit.

This article makes occasional use of thealternative syntax for lambda abstraction terms, where λxyz.N is abbreviated as λxyz.N, as well as the two standard combinators,Iλx.x{\displaystyle I\equiv \lambda x.x} andKλxy.x{\displaystyle K\equiv \lambda xy.x}, as needed.

Church pairs

[edit]
See also:Cons

Church pairs are the Church encoding of thepair (two-tuple) type. The pair is represented as a function that takes a function argument. The pair itself does not decide what to do with the elements of the tuple. When given its argument it will apply the argument to the two components of the pair. The definition of the pair, theselect first element and theselect second element functions inlambda calculus are,

pairλxy.λz.z x yfirstλp.p (λxy.x)secondλp.p (λxy.y){\displaystyle {\begin{aligned}\operatorname {pair} &\equiv \lambda xy.\lambda z.z\ x\ y\\\operatorname {first} &\equiv \lambda p.p\ (\lambda xy.x)\\\operatorname {second} &\equiv \lambda p.p\ (\lambda xy.y)\end{aligned}}}

For example,

first (pair a b)= (λp.p (λxy.x)) ((λxyz.z x y) a b)= (λp.p (λxy.x)) (λz.z a b)= (λz.z a b) (λxy.x)= (λxy.x) a b= a{\displaystyle {\begin{aligned}&\operatorname {first} \ (\operatorname {pair} \ a\ b)\\=&\ (\lambda p.p\ (\lambda xy.x))\ ((\lambda xyz.z\ x\ y)\ a\ b)\\=&\ (\lambda p.p\ (\lambda xy.x))\ (\lambda z.z\ a\ b)\\=&\ (\lambda z.z\ a\ b)\ (\lambda xy.x)\\=&\ (\lambda xy.x)\ a\ b\\=&\ a\end{aligned}}}

Church Booleans

[edit]

Church Booleans encode the Boolean valuestrue andfalse. Some programming languages use these as an implementation model for Boolean arithmetic; examples areSmalltalk andPico.

Boolean logic embodies achoice betweentwo alternatives. Thus the Church encodings oftrue andfalse are functions of two parameters:

  • true chooses the first parameter ;
  • false chooses the second parameter.

The two definitions in lambda calculus are:

trueλa.λb.afalseλa.λb.b{\displaystyle {\begin{aligned}\operatorname {true} &\equiv \lambda a.\lambda b.a\\\operatorname {false} &\equiv \lambda a.\lambda b.b\end{aligned}}}

These definitions allow predicates (i.e. functions returninglogical values) to directly act asif-test clauses, so thatif operator is just an identity function, and thus can be omitted. Each logical value already acts as anif, performing a choice between its two arguments. A Boolean value applied to two values returns either the first or the second value. The expression

test-clause then-clause else-clause{\displaystyle \operatorname {test-clause} \ \operatorname {then-clause} \ \operatorname {else-clause} }

returnsthen-clause iftest-clause istrue, andelse-clause iftest-clause isfalse.

Because logical values liketrue andfalse choose their first or second argument, they can be combined to provide logical operators. Several implementations are usually possible, whether by directly manipulating parameters or by reducing to the more basic logical values. Here are the definitions, using the shortened notation as mentioned at the start of the article (p,q are predicates;a,b are general values):

if=λpab.p a b and=λpq.p q p=λpqab.p (q a b) bor=λpq.p p q=λpqab.p a (q a b)not=λp.pfalsetrue=λpab  .p b axor=λpq.p (not q) q=λpqab.p (q b a) (q a b)nand=λpq.not (andp q)=λpqab.p (q b a) aimplies=λpq.or (notp) q=λpqab.p (q a b) a{\displaystyle {\begin{aligned}\operatorname {if} &=\lambda pab.p\ a\ b&&\ \\\operatorname {and} &=\lambda pq.p\ q\ p&&=\lambda pqab.p\ (q\ a\ b)\ b\\\operatorname {or} &=\lambda pq.p\ p\ q&&=\lambda pqab.p\ a\ (q\ a\ b)\\\operatorname {not} &=\lambda p.p\operatorname {false} \operatorname {true} &&=\lambda pab\ \ .p\ b\ a\\\operatorname {xor} &=\lambda pq.p\ (\operatorname {not} \ q)\ q&&=\lambda pqab.p\ (q\ b\ a)\ (q\ a\ b)\\\operatorname {nand} &=\lambda pq.\operatorname {not} \ (\operatorname {and} p\ q)&&=\lambda pqab.p\ (q\ b\ a)\ a\\\operatorname {implies} &=\lambda pq.\operatorname {or} \ (\operatorname {not} p)\ q&&=\lambda pqab.p\ (q\ a\ b)\ a\\\end{aligned}}}

Some examples:

andtruefalse=(λp.λq.p q p) true false=truefalsetrue=(λa.λb.a)falsetrue=falseortruefalse=(λp.λq.p p q) (λa.λb.a) (λa.λb.b)=(λa.λb.a) (λa.λb.a) (λa.λb.b)=(λa.λb.a)=truenot2 true=(λp.λa.λb.p b a)(λa.λb.a)=λa.λb.(λa.λb.a) b a=λa.λb.(λc.b) a=λa.λb.b=falsenot1 true=(λp.p (λa.λb.b) (λa.λb.a)) (λa.λb.a)=(λa.λb.a) (λa.λb.b) (λa.λb.a)=(λb.(λa.λb.b)) (λa.λb.a)=λa.λb.b=false{\displaystyle {\begin{aligned}\operatorname {and} \operatorname {true} \operatorname {false} &=(\lambda p.\lambda q.p\ q\ p)\ \operatorname {true} \ \operatorname {false} \\&=\operatorname {true} \operatorname {false} \operatorname {true} \\&=(\lambda a.\lambda b.a)\operatorname {false} \operatorname {true} \\&=\operatorname {false} \\\\\operatorname {or} \operatorname {true} \operatorname {false} &=(\lambda p.\lambda q.p\ p\ q)\ (\lambda a.\lambda b.a)\ (\lambda a.\lambda b.b)\\&=(\lambda a.\lambda b.a)\ (\lambda a.\lambda b.a)\ (\lambda a.\lambda b.b)\\&=(\lambda a.\lambda b.a)\\&=\operatorname {true} \\\\\operatorname {not} _{2}\ \operatorname {true} &=(\lambda p.\lambda a.\lambda b.p\ b\ a)(\lambda a.\lambda b.a)\\&=\lambda a.\lambda b.(\lambda a.\lambda b.a)\ b\ a\\&=\lambda a.\lambda b.(\lambda c.b)\ a\\&=\lambda a.\lambda b.b\\&=\operatorname {false} \\\\\operatorname {not} _{1}\ \operatorname {true} &=(\lambda p.\,p\ (\lambda a.\lambda b.\,b)\ (\lambda a.\lambda b.\,a))\ (\lambda a.\lambda b.\,a)\\&=(\lambda a.\lambda b.\,a)\ (\lambda a.\lambda b.\,b)\ (\lambda a.\lambda b.\,a)\\&=(\lambda b.\,(\lambda a.\lambda b.\,b))\ (\lambda a.\lambda b.\,a)\\&=\lambda a.\lambda b.\,b\\&=\operatorname {false} \end{aligned}}}

Church numerals

[edit]

Church numerals are the representations ofnatural numbers under Church encoding. Thehigher-order function that represents natural numbern is a function that maps any functionf{\displaystyle f} to itsn-foldcomposition. In simpler terms, a numeral represents the number by applying any given function that number of times in sequence, starting from any given starting value:

n:ffn{\displaystyle n:f\mapsto f^{\circ n}}
fn(x)=(fffn times)(x)=f(f((fn times(x)))){\displaystyle f^{\circ n}(x)=(\underbrace {f\circ f\circ \ldots \circ f} _{n{\text{ times}}})\,(x)=\underbrace {f(f(\ldots (f} _{n{\text{ times}}}\,(x))\ldots ))}

Church encoding is thus aunary encoding of natural numbers,[1] corresponding to simplecounting. Each Church numeral achieves this by construction.

All Church numerals are functions that take two parameters. Church numerals0,1,2, ..., are defined as follows in thelambda calculus:

Starting with0not applying the function at all, proceed with1applying the function once,2 applying the function twice in a row,3applying the function three times in a row, etc.:
NumberFunction definitionLambda expression00 f x=x0=λf.λx.x11 f x=f x1=λf.λx.f x22 f x=f (f x)2=λf.λx.f (f x)33 f x=f (f (f x))3=λf.λx.f (f (f x))nn f x=fn xn=λf.λx.fn x{\displaystyle {\begin{array}{r|l|l}{\text{Number}}&{\text{Function definition}}&{\text{Lambda expression}}\\\hline 0&0\ f\ x=x&0=\lambda f.\lambda x.x\\1&1\ f\ x=f\ x&1=\lambda f.\lambda x.f\ x\\2&2\ f\ x=f\ (f\ x)&2=\lambda f.\lambda x.f\ (f\ x)\\3&3\ f\ x=f\ (f\ (f\ x))&3=\lambda f.\lambda x.f\ (f\ (f\ x))\\\vdots &\vdots &\vdots \\n&n\ f\ x=f^{\circ n}\ x&n=\lambda f.\lambda x.f^{\circ n}\ x\end{array}}}

The Church numeral3 is a chain of three applications of any given function in sequence, starting from some value. The supplied function is first applied to a supplied argument and then successively to its own result. The end result is not the number 3 (unless the supplied parameter happens to be 0 and the function is asuccessor function). The function itself, and not its end result, is the Church numeral3. The Church numeral3 means simply to do something three times. It is anostensive demonstration of what is meant by "three times".

Calculation with Church numerals

[edit]

Arithmetic operations on numbers produce numbers as their results. In Church encoding, these operations are represented bylambda abstractions which, when applied to Church numerals representing the operands, beta-reduce to the Church numerals representing the results.

Church representation of addition,plus(m,n)=m+n{\displaystyle \operatorname {plus} (m,n)=m+n}, uses the identityf(m+n)(x)=(fmfn)(x)=fm(fn(x)){\displaystyle f^{\circ (m+n)}(x)=(f^{\circ m}\circ f^{\circ n})(x)=f^{\circ m}(f^{\circ n}(x))}:

plusλmn.λfx.m f (n f x){\displaystyle \operatorname {plus} \equiv \lambda mn.\lambda fx.m\ f\ (n\ f\ x)}

The successor operation,succ(n)=n+1{\displaystyle \operatorname {succ} (n)=n+1}, is obtained byβ-reducing the expression "plus 1{\displaystyle \operatorname {plus} \ 1}":

succλn.λfx.f (n f x){\displaystyle \operatorname {succ} \equiv \lambda n.\lambda fx.f\ (n\ f\ x)}

Multiplication,mult(m,n)=mn{\displaystyle \operatorname {mult} (m,n)=m*n}, uses the identityf(mn)(x)=(fn)m(x){\displaystyle f^{\circ (m*n)}(x)=(f^{\circ n})^{\circ m}(x)}:

multλmn.λfx.m (n f) x{\displaystyle \operatorname {mult} \equiv \lambda mn.\lambda fx.m\ (n\ f)\ x}

Thusb (b f)(multb b) f{\displaystyle b\ (b\ f)\equiv (\operatorname {mult} b\ b)\ f} andb (b (b f))(multb (multb b)) f{\displaystyle b\ (b\ (b\ f))\equiv (\operatorname {mult} b\ (\operatorname {mult} b\ b))\ f}, and so by the virtue of Church encoding expressing then-fold composition, the exponentiation operationexp(b,n)=bn{\displaystyle \operatorname {exp} (b,n)=b^{n}} is given by

expλbn.n bλbnfx.n b f x{\displaystyle \operatorname {exp} \equiv \lambda bn.n\ b\equiv \lambda bnfx.n\ b\ f\ x}

The predecessor operationpred(n){\displaystyle \operatorname {pred} (n)} is a little bit more involved. We need to devise an operation that when repeatedn+1{\displaystyle n+1} times will result inn{\displaystyle n} applications of the given functionf{\displaystyle f}. This is achieved by using the identity function instead, one time only, and then switching back tof{\displaystyle f}:

predλnfx.n (λri.i (r f)) (λf.x) I{\displaystyle \operatorname {pred} \equiv \lambda nfx.n\ (\lambda ri.i\ (r\ f))\ (\lambda f.x)\ I}

As previously mentioned,I{\displaystyle I} is the identity function,λx.x{\displaystyle \lambda x.x}. See below for a detailed explanation. This suggests implementing e.g. halving and factorial in the similar fashion,

halfλnfx.n (λrab.a (r b a)) (λab.x) I ffactλnf.n (λra.a (r (succa))) (λa.f) 1{\displaystyle {\begin{aligned}\operatorname {half} &\equiv \lambda nfx.n\ (\lambda rab.a\ (r\ b\ a))\ (\lambda ab.x)\ I\ f\\\operatorname {fact} &\equiv \lambda nf.n\ (\lambda ra.a\ (r\ (\operatorname {succ} a)))\ (\lambda a.f)\ 1\end{aligned}}}

For example,pred4 f x{\displaystyle \operatorname {pred} 4\ f\ x\,} beta-reduces toI(f (f (f x))){\displaystyle I(f\ (f\ (f\ x)))},half 5 f x{\displaystyle \operatorname {half} \ 5\ f\ x\,} beta-reduces toI (f (I (f (I x)))){\displaystyle I\ (f\ (I\ (f\ (I\ x))))}, andfact4f{\displaystyle \operatorname {fact} 4\,f\,} beta-reduces to1 (2 (3 (4 f))){\displaystyle 1\ (2\ (3\ (4\ f)))}.

Subtraction,minus(m,n)=mn{\displaystyle minus(m,n)=m-n}, is expressed by repeated application of the predecessor operation a given number of times, just like addition can be expressed by repeated application of the successor operation a given number of times, etc.:

minusλmn.npred mplusλmn.nsucc mmultλmn.n (mplus) 0expλmn.n (mmult) 1    {  mn }tetλmn.n (mexp) 1    { m↑↑n }{\displaystyle {\begin{aligned}\operatorname {minus} &\equiv \lambda mn.n\operatorname {pred} \ m\\\operatorname {plus} &\equiv \lambda mn.n\operatorname {succ} \ m\\\operatorname {mult} &\equiv \lambda mn.n\ (m\operatorname {plus} )\ 0\\\operatorname {exp} &\equiv \lambda mn.n\ (m\operatorname {mult} )\ 1\ \ \ \ \{-\ \ m^{n}\ -\}\\\operatorname {tet} &\equiv \lambda mn.n\ (m\operatorname {exp} )\ 1\ \ \ \ \{-\ m\uparrow \uparrow n\ -\}\end{aligned}}}

tet{\displaystyle \operatorname {tet} } is thetetration operation,tet m 3=m(m(m1)){\displaystyle \operatorname {tet} \ m\ 3=m^{(m^{(m^{1})})}}. Similarly to the factorial definition above, it can also be defined by using the intrinsic properties of the Church encoding, creating the "code" expression for it and letting the Church numerals themselves do the rest:

tetrλn.n (λra.r a a) 0{\displaystyle {\begin{aligned}\operatorname {tetr} &\equiv \lambda n.n\ (\lambda ra.r\ a\ a)\ 0\end{aligned}}}

Heretetr 3 a=0 a a a a=a a a=a(aa){\displaystyle \operatorname {tetr} \ 3\ a=0\ a\ a\ a\ a=a\ a\ a=a^{(a^{a})}}.

Direct Subtraction and Division

[edit]

Just as addition as repeated successor has its counterpart in the direct style, so can subtraction be expressed directly and more efficiently as well:

minusλmnfx.m (λrq.q r) (λq.x)(n (λqr.r q) (Y (λqr.f (r q)))){\displaystyle {\begin{aligned}\operatorname {minus} \equiv \lambda &mnfx.\\&m\ (\lambda rq.q\ r)\ (\lambda q.x)\\&(n\ (\lambda qr.r\ q)\ (\operatorname {Y} \ (\lambda qr.f\ (r\ q))))\end{aligned}}}

For example,minus 6 3 f x{\displaystyle \operatorname {minus} \ 6\ 3\ f\ x} reduces to an equivalent off (2 f x){\displaystyle f\ (2\ f\ x)}.

This also gives another predecessor version, beta-reducingλm.minus m 1{\displaystyle \lambda m.\operatorname {minus} \ m\ 1} :

predλmfx.m (λrq.q r) (λq.x)(λr.r (Y (λqr.f (r q)))){\displaystyle {\begin{aligned}\operatorname {pred'} \equiv \lambda mfx.m\ &(\lambda rq.q\ r)\ (\lambda q.x)\\&(\lambda r.r\ (\operatorname {Y} \ (\lambda qr.f\ (r\ q))))\end{aligned}}}

Direct definition of division is given quite similarly as

divλmnfx.m (λrq.q r) (λq.x)(Y (λq.n (λqr.r q) (λr.f (r q)) (λx.x))){\displaystyle {\begin{aligned}\operatorname {div} \equiv \lambda &mnfx.\\&m\ (\lambda rq.q\ r)\ (\lambda q.x)\\&(\operatorname {Y} \ (\lambda q.n\ (\lambda qr.r\ q)\ (\lambda r.f\ (r\ q))\ (\lambda x.x)))\end{aligned}}}

The application to(λx.x){\displaystyle (\lambda x.x)} achieves subtraction by1{\displaystyle 1} while creating a cycle of actions repeatedly emitting anf{\displaystyle f} aftern1{\displaystyle n-1} steps.

Instead ofY{\displaystyle \operatorname {Y} },(λq.mqx){\displaystyle (\lambda q.m\,q\,x)} can also be used in each of the three definitions above.

Table of functions on Church numerals

[edit]
FunctionAlgebraIdentityFunction definitionLambda expressions
Successorn+1{\displaystyle n+1}f(n+1)=ffn{\displaystyle f^{\circ (n+1)}=f\circ f^{\circ n}}succ n f x=f (n f x){\displaystyle \operatorname {succ} \ n\ f\ x=f\ (n\ f\ x)}λnfx.f (n f x){\displaystyle \lambda nfx.f\ (n\ f\ x)}...
Additionm+n{\displaystyle m+n}f(m+n)=fmfn{\displaystyle f^{\circ (m+n)}=f^{\circ m}\circ f^{\circ n}}plus m n f x=m f (n f x){\displaystyle \operatorname {plus} \ m\ n\ f\ x=m\ f\ (n\ f\ x)}λmnfx.m f (n f x){\displaystyle \lambda mnfx.m\ f\ (n\ f\ x)}λmn.nsuccm{\displaystyle \lambda mn.n\operatorname {succ} m}
Multiplicationmn{\displaystyle m*n}f(mn)=(fm)n{\displaystyle f^{\circ (m*n)}=(f^{\circ m})^{\circ n}}multiply m n f x=m (n f) x{\displaystyle \operatorname {multiply} \ m\ n\ f\ x=m\ (n\ f)\ x}λmnfx.m (n f) x{\displaystyle \lambda mnfx.m\ (n\ f)\ x}λmnf.m (n f){\displaystyle \lambda mnf.m\ (n\ f)}
Exponentiationbn{\displaystyle b^{n}}bn=(multb)n{\displaystyle b^{\circ n}=(\operatorname {mult} b)^{\circ n}}exp b n f x=n b f x{\displaystyle \operatorname {exp} \ b\ n\ f\ x=n\ b\ f\ x}λbnfx.n b f x{\displaystyle \lambda bnfx.n\ b\ f\ x}λbn.n b{\displaystyle \lambda bn.n\ b}
Predecessor[a]n1{\displaystyle n-1}first((i,jj,fj)nI,I)=f(n1){\displaystyle first((\langle i,j\rangle \mapsto \langle j,f\circ j\rangle )^{\circ n}\langle I,I\rangle )=f^{\circ (n-1)}}pred(n+1) f x=I (n f x){\displaystyle \operatorname {pred} (n+1)\ f\ x=I\ (n\ f\ x)}

λnfx.n (λri.i (r f)) (λf.x) (λu.u){\displaystyle \lambda nfx.n\ (\lambda ri.i\ (r\ f))\ (\lambda f.x)\ (\lambda u.u)}

Subtraction[a] (Monus)mn{\displaystyle m-n}mn=predn(m){\displaystyle m-n=pred^{\circ n}(m)}minus m n=npredm{\displaystyle \operatorname {minus} \ m\ n=n\operatorname {pred} m}...λmn.npredm{\displaystyle \lambda mn.n\operatorname {pred} m}

Notes:

  1. ^abIn the Church encoding,

Predecessor function

[edit]

The predecessor function is given as

predλnfx.n (λri.i (r f)) (λf.x) (λu.u){\displaystyle \operatorname {pred} \equiv \lambda nfx.n\ (\lambda ri.i\ (r\ f))\ (\lambda f.x)\ (\lambda u.u)}

This encoding essentially uses the identity

first( (i,jj,fj)nI,I )={Iif n=0,f(n1)otherwise{\displaystyle first(\ (\langle i,j\rangle \mapsto \langle j,f\circ j\rangle )^{\circ n}\langle I,I\rangle \ )={\begin{cases}I&{\mbox{if }}n=0,\\f^{\circ (n-1)}&{\mbox{otherwise}}\end{cases}}}

or

first( (x,yy,f(y))nx,x )={xif n=0,f(n1)(x)otherwise{\displaystyle first(\ (\langle x,y\rangle \mapsto \langle y,f(y)\rangle )^{\circ n}\langle x,x\rangle \ )={\begin{cases}x&{\mbox{if }}n=0,\\f^{\circ (n-1)}(x)&{\mbox{otherwise}}\end{cases}}}

An explanation of pred

[edit]

The idea here is as follows. The only thing known to the Church numeralpredn{\displaystyle \operatorname {pred} n} is the numeraln{\displaystyle n} itself. Given two argumentsf{\displaystyle f} andx{\displaystyle x}, as usual, the only thing it can do is to apply that numeral to the two arguments, somehow modified so that then-long chain of applications thus created will have one (specifically, leftmost)f{\displaystyle f} in the chain replaced by the identity function:

f(n1)(x)=I (f(f((fn1 timesn times(x)))))=(Xf)n(Zx) A=Xf (Xf ((Xfn times(Zx)))) A=X f r1 A1{ and it must be equal to: }=I (X f r2 A2)=I (f (X f r3 A3))=I (f (f (X f r4 A4)))=I (f (f (X f rn An)))=I (f (f (fn times (Z x An+1)))){\displaystyle {\begin{aligned}f^{\circ (n-1)}(x)&=\underbrace {I\ (\underbrace {f(f(\ldots (f} _{{n-1}{\text{ times}}}} _{n{\text{ times}}}\,(x))\ldots )))=(Xf)^{\circ n}(Z\,x)\ A\\&=\underbrace {Xf\ (Xf\ (\ldots (Xf} _{{n}{\text{ times}}}\,(Z\,x))\ldots ))\ A\\&=X\ f\ r_{1}\ A_{1}\,\,\,\{-\ and\ it\ must\ be\ equal\ to:\ -\}\\&=I\ (X\ f\ r_{2}\ A_{2})\\&=I\ (f\ (X\ f\ r_{3}\ A_{3}))\\&=I\ (f\ (f\ (X\ f\ r_{4}\ A_{4})))\\&\ldots \\&=I\ (f\ (f\ \ldots (X\ f\ r_{n}\ A_{n})\ldots ))\\&=\underbrace {I\ (f\ (f\ \ldots (f} _{n{\text{ times}}}\ (Z\ x\ A_{n+1}))\ldots ))\\\end{aligned}}}

HereXf{\displaystyle Xf} is the modifiedf{\displaystyle f}, andZx{\displaystyle Z\,x} is the modifiedx{\displaystyle x}. SinceXf{\displaystyle Xf} itself can not be changed, its behavior can only be modified through an additional argument,A{\displaystyle A}.

The goal is achieved, then, by passing that additional argumentA{\displaystyle A} alongfrom the outside in, while modifying it as necessary, with the definitions

A1=IAi>1=fZ x f=x=K x fX f r Ai=Ai (r Ai+1){ i.e., }X f r i=i (r f){\displaystyle {\begin{aligned}A_{1}\,\,\,\,\,\,\,\,\,\,&=\,I\\A_{\,i>1}\,\,\,\,\,&=\,f\\Z\ x\ f\,\,\,\,&=x=K\ x\ f\\X\ f\ r\ A_{i}&=A_{i}\ (r\ A_{i+1})\,\,\,\,\,\,\{-\ i.e.,\ -\}\\X\ f\ r\ i\,\,\,\,\,&=i\ (r\ f)\end{aligned}}}

Which is exactly what we have in thepred{\displaystyle \operatorname {pred} } definition's lambda expression.

Now it is easy enough to see that

pred (succ n) f x=succ n (Xf) (K x) I=X f (n (X f) (K x)) I=I (n (Xf) (K x) f)= =I (f (f (f (K xf))))=I (n f x)=n f x {\displaystyle {\begin{aligned}\operatorname {pred} \ (\operatorname {succ} \ n)\ f\ x&=\operatorname {succ} \ n\ (Xf)\ (K\ x)\ I\\&=X\ f\ (n\ (X\ f)\ (K\ x))\ I\\&=I\ (n\ (Xf)\ (K\ x)\ \,\,f\,\,\,)\\&=\ \ldots \\&=I\ (f\ (f\ \ldots (f\ (K\ x\,\,f\,\,))\ldots ))\\&=I\ (n\ f\ x)\\&=n\ f\ x\ \end{aligned}}}
pred 0 f x= 0 (Xf) (K x) I= K x I= x= 0 f x{\displaystyle {\begin{aligned}\operatorname {pred} \ 0\ f\ x&=\ 0\ (Xf)\ (K\ x)\ I\\&=\ K\ x\ I\\&=\ x\\&=\ 0\ f\ x\end{aligned}}}

i.e. by eta-contraction and then by induction, it holds that

pred (succ n)= npred 0= 0pred (pred 0)= pred 0 = 0{\displaystyle {\begin{aligned}&\operatorname {pred} \ (\operatorname {succ} \ n)&&=\ n\\&\operatorname {pred} \ 0&&=\ 0\\&\operatorname {pred} \ (\operatorname {pred} \ 0)&&=\ \operatorname {pred} \ 0\ =\ 0\\&\ldots \end{aligned}}}

and so on.

Defining pred through pairs

[edit]

The identityabove may be coded with the explicit use of pairs. It can be done in several ways, for instance,

f= λp. pair (second p) (succ (second p))pred2= λn. first (n f (pair 0 0)){\displaystyle {\begin{aligned}\operatorname {f} =&\ \lambda p.\ \operatorname {pair} \ (\operatorname {second} \ p)\ (\operatorname {succ} \ (\operatorname {second} \ p))\\\operatorname {pred} _{2}=&\ \lambda n.\ \operatorname {first} \ (n\ \operatorname {f} \ (\operatorname {pair} \ 0\ 0))\\\end{aligned}}}

The expansion forpred23{\displaystyle \operatorname {pred} _{2}3} is:

pred23= first (f (f (f (pair 0 0))))= first (f (f (pair 0 1)))= first (f (pair 1 2))= first (pair 2 3)= 2{\displaystyle {\begin{aligned}\operatorname {pred} _{2}3=&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {pair} \ 0\ 0))))\\=&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {f} \ (\operatorname {pair} \ 0\ 1)))\\=&\ \operatorname {first} \ (\operatorname {f} \ (\operatorname {pair} \ 1\ 2))\\=&\ \operatorname {first} \ (\operatorname {pair} \ 2\ 3)\\=&\ 2\end{aligned}}}

This is a simpler definition to devise but leads to a more complex lambda expression,

pred2λn.n (λp.p (λabh.h b (succ b)))(λh.h 0 0)(λab.a){\displaystyle {\begin{aligned}\operatorname {pred} _{2}\equiv \lambda n.n\ &(\lambda p.p\ (\lambda abh.h\ b\ (\operatorname {succ} \ b)))\,\,(\lambda h.h\ 0\ 0)\,\,(\lambda ab.a)\end{aligned}}}

Pairs in the lambda calculus are essentially just extra arguments, whether passing them inside out like here, or from the outside in as in the originalpred{\displaystyle \operatorname {pred} } definition. Another encoding follows the second variant of the predecessor identity directly,

pred3λnfx.n (λp.p (λabh.h b (f b)))(λh.h x x)(λab.a){\displaystyle {\begin{aligned}\operatorname {pred} _{3}\equiv \lambda nfx.n\ &(\lambda p.p\ (\lambda abh.h\ b\ (f\ b)))\,\,(\lambda h.h\ x\ x)\,\,(\lambda ab.a)\end{aligned}}}

This way it is already quite close to the original, "outside-in"pred{\displaystyle \operatorname {pred} } definition, also creating the chain off{\displaystyle f}s like it does, only in a bit more wasteful way still. But it is very much less wasteful than the previous,pred2{\displaystyle \operatorname {pred} _{2}} definition here. Indeed if we trace its execution we arrive at the new, even more streamlined, yet fully equivalent, definition

pred4λnfx.n (λrab.r b (f b))K x x{\displaystyle {\begin{aligned}\operatorname {pred} _{4}\equiv \lambda nfx.n\ &(\lambda rab.r\ b\ (f\ b))\,K\ x\ x\end{aligned}}}

which makes it fully clear and apparent that this is all about just argument modification and passing. Its reduction proceeds as

pred43 f x= (..(..(..K))) x x= (..(..K))x (f x)= (..K)(f x) (f (f x))= K(f (f x)) (f (f (f x)))= f (f x){\displaystyle {\begin{aligned}\operatorname {pred} _{4}3\ f\ x&=\ (..(..(..K)))\ x\ \,x\\&=\ (..(..K))\,\,\,\,\,\,\,x\ \,\,(f\ x)\\&=\ (..K)\,\,\,\,\,\,(f\ x)\ \,\,(f\ (f\ x))\\&=\ K\,\,\,\,(f\ (f\ x))\ \,\,(f\ (f\ (f\ x)))\\&=\ f\ (f\ x)\\\end{aligned}}}

clearly showing what is going on. Still, the originalpred{\displaystyle \operatorname {pred} } is much preferable since it's working in the top-down manner and is thus able to stop right away if the user-supplied functionf{\displaystyle f} is short-circuiting. The top-down approach is also used with other definitions like

pred5λnfx.n (λrab.a (r b b))(λab.x) I fthirdλnfx.n (λrabc.a (r b c a))(λabc.x) I I fthirdRoundedλnfx.n (λrabc.a (r b c a))(λabc.x) I f ItwoThirdsλnfx.n (λrabc.a (r b c a))(λabc.x) I f ffactorialλnfx.n (λra.a (r (succa)))(λa.f) 1 x{\displaystyle {\begin{aligned}\operatorname {pred} _{5}\equiv \lambda nfx.n\ &(\lambda rab.a\ (r\ b\ b))\,(\lambda ab.x)\ I\ f\\\operatorname {third} \equiv \lambda nfx.n\ &(\lambda rabc.a\ (r\ b\ c\ a))\,(\lambda abc.x)\ I\ I\ f\\\operatorname {thirdRounded} \equiv \lambda nfx.n\ &(\lambda rabc.a\ (r\ b\ c\ a))\,(\lambda abc.x)\ I\ f\ I\\\operatorname {twoThirds} \equiv \lambda nfx.n\ &(\lambda rabc.a\ (r\ b\ c\ a))\,(\lambda abc.x)\ I\ f\ f\\\operatorname {factorial} \equiv \lambda nfx.n\ &(\lambda ra.a\ (r\ (\operatorname {succ} a)))\,(\lambda a.f)\ 1\ x\\\end{aligned}}}

Division via General Recursion

[edit]

Division of natural numbers may be implemented by,[2]

n/m=if nm then 1+(nm)/m else 0{\displaystyle n/m=\operatorname {if} \ n\geq m\ \operatorname {then} \ 1+(n-m)/m\ \operatorname {else} \ 0}

Calculatingnm{\displaystyle n-m} withλnm.mpredn{\displaystyle \lambda nm.m\,\operatorname {pred} \,n} takes many beta reductions. Unless doing the reduction by hand, this doesn't matter that much, but it is preferable to not have to do this calculation twice (unless the direct subtraction definition is used, see above). The simplest predicate for testing numbers isIsZero so consider the condition.

IsZero (minus n m){\displaystyle \operatorname {IsZero} \ (\operatorname {minus} \ n\ m)}

But this condition is equivalent tonm{\displaystyle n\leq m}, notn<m{\displaystyle n<m}. If this expression is used then the mathematical definition of division given above is translated into function on Church numerals as,

divide1 n m f x=(λd.IsZero d (0 f x) (f (divide1 d m f x))) (minus n m){\displaystyle \operatorname {divide1} \ n\ m\ f\ x=(\lambda d.\operatorname {IsZero} \ d\ (0\ f\ x)\ (f\ (\operatorname {divide1} \ d\ m\ f\ x)))\ (\operatorname {minus} \ n\ m)}

As desired, this definition has a single call tominus n m{\displaystyle \operatorname {minus} \ n\ m}. However the result is that this formula gives the value of(n1)/m{\displaystyle (n-1)/m}.

This problem may be corrected by adding 1 ton before callingdivide. The definition ofdivide is then,

divide n=divide1 (succ n){\displaystyle \operatorname {divide} \ n=\operatorname {divide1} \ (\operatorname {succ} \ n)}

divide1 is a recursive definition. TheY combinator may be used to implement the recursion. Create a new function calleddiv by;

to get,

div=λc.λn.λm.λf.λx.(λd.IsZero d (0 f x) (f (c d m f x))) (minus n m){\displaystyle \operatorname {div} =\lambda c.\lambda n.\lambda m.\lambda f.\lambda x.(\lambda d.\operatorname {IsZero} \ d\ (0\ f\ x)\ (f\ (c\ d\ m\ f\ x)))\ (\operatorname {minus} \ n\ m)}

Then,

divide=λn.divide1 (succ n){\displaystyle \operatorname {divide} =\lambda n.\operatorname {divide1} \ (\operatorname {succ} \ n)}

where,

divide1=Y divsucc=λn.λf.λx.f (n f x)Y=λf.(λx.f (x x)) (λx.f (x x))0=λf.λx.xIsZero=λn.n (λx.false) true{\displaystyle {\begin{aligned}\operatorname {divide1} &=Y\ \operatorname {div} \\\operatorname {succ} &=\lambda n.\lambda f.\lambda x.f\ (n\ f\ x)\\Y&=\lambda f.(\lambda x.f\ (x\ x))\ (\lambda x.f\ (x\ x))\\0&=\lambda f.\lambda x.x\\\operatorname {IsZero} &=\lambda n.n\ (\lambda x.\operatorname {false} )\ \operatorname {true} \end{aligned}}}
trueλa.λb.afalseλa.λb.b{\displaystyle {\begin{aligned}\operatorname {true} &\equiv \lambda a.\lambda b.a\\\operatorname {false} &\equiv \lambda a.\lambda b.b\end{aligned}}}
minus=λm.λn.npredmpred=λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u){\displaystyle {\begin{aligned}\operatorname {minus} &=\lambda m.\lambda n.n\operatorname {pred} m\\\operatorname {pred} &=\lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u)\end{aligned}}}

Gives,

divide=λn.((λf.(λx.x x) (λx.f (x x))) (λc.λn.λm.λf.λx.(λd.(λn.n (λx.(λa.λb.b)) (λa.λb.a)) d ((λf.λx.x) f x) (f (c d m f x))) ((λm.λn.n(λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u))m) n m))) ((λn.λf.λx.f (n f x)) n){\displaystyle \scriptstyle \operatorname {divide} =\lambda n.((\lambda f.(\lambda x.x\ x)\ (\lambda x.f\ (x\ x)))\ (\lambda c.\lambda n.\lambda m.\lambda f.\lambda x.(\lambda d.(\lambda n.n\ (\lambda x.(\lambda a.\lambda b.b))\ (\lambda a.\lambda b.a))\ d\ ((\lambda f.\lambda x.x)\ f\ x)\ (f\ (c\ d\ m\ f\ x)))\ ((\lambda m.\lambda n.n(\lambda n.\lambda f.\lambda x.n\ (\lambda g.\lambda h.h\ (g\ f))\ (\lambda u.x)\ (\lambda u.u))m)\ n\ m)))\ ((\lambda n.\lambda f.\lambda x.f\ (n\ f\ x))\ n)}

Or as text, using \ forλ,

divide = (\n.((\f.(\x.x x) (\x.f (x x))) (\c.\n.\m.\f.\x.(\d.(\n.n (\x.(\a.\b.b)) (\a.\b.a)) d ((\f.\x.x) f x) (f (c d m f x))) ((\m.\n.n (\n.\f.\x.n (\g.\h.h (g f)) (\u.x) (\u.u)) m) n m))) ((\n.\f.\x. f (n f x)) n))

For example, 9/3 is represented by

divide (\f.\x.f (f (f (f (f (f (f (f (f x))))))))) (\f.\x.f (f (f x)))

Using a lambda calculus calculator, the above expression reduces to 3, using normal order.

\f.\x.f (f (f (x)))

Predicates

[edit]

Apredicate is a function that returns a Boolean value. The most fundamental predicate on Church numerals isIsZero{\displaystyle \operatorname {IsZero} }, which returnstrue{\displaystyle \operatorname {true} } if its argument is the Church numeral0{\displaystyle 0}, andfalse{\displaystyle \operatorname {false} } otherwise:

IsZero=λn.n (λx.false) true{\displaystyle \operatorname {IsZero} =\lambda n.n\ (\lambda x.\operatorname {false} )\ \operatorname {true} }

The following predicate tests whether the first argument is less-than-or-equal-to the second:

LEQ=λm.λn.IsZero (minus m n){\displaystyle \operatorname {LEQ} =\lambda m.\lambda n.\operatorname {IsZero} \ (\operatorname {minus} \ m\ n)}

Because of the identity

x=y(xyyx){\displaystyle x=y\equiv (x\leq y\land y\leq x)}

the test for equality can be implemented as

EQ=λm.λn.and (LEQ m n) (LEQ n m){\displaystyle \operatorname {EQ} =\lambda m.\lambda n.\operatorname {and} \ (\operatorname {LEQ} \ m\ n)\ (\operatorname {LEQ} \ n\ m)}

In programming languages

[edit]

Most real-world languages have support for machine-native integers; thechurch andunchurch functions convert between nonnegative integers and their corresponding Church numerals. The functions are given here inHaskell, where the\ corresponds to the λ of Lambda calculus. Implementations in other languages are similar.

typeChurcha=(a->a)->a->achurch::Integer->ChurchIntegerchurch0=\f->\x->xchurchn=\f->\x->f(church(n-1)fx)unchurch::ChurchInteger->Integerunchurchcn=cn(+1)0

Signed numbers

[edit]

One simple approach for extending Church Numerals tosigned numbers is to use a Church pair, containing Church numerals representing a positive and a negative value.[3] The integer value is the difference between the two Church numerals.

A natural number is converted to a signed number by,

converts=λx.pair x 0{\displaystyle \operatorname {convert} _{s}=\lambda x.\operatorname {pair} \ x\ 0}

Negation is performed by swapping the values.

negs=λx.pair (second x) (first x){\displaystyle \operatorname {neg} _{s}=\lambda x.\operatorname {pair} \ (\operatorname {second} \ x)\ (\operatorname {first} \ x)}

The integer value is more naturally represented if one of the pair is zero. TheOneZero function achieves this condition,

OneZero=λx.IsZero (first x) x (IsZero (second x) x (OneZero (pair (pred (first x)) (pred (second x))))){\displaystyle \operatorname {OneZero} =\lambda x.\operatorname {IsZero} \ (\operatorname {first} \ x)\ x\ (\operatorname {IsZero} \ (\operatorname {second} \ x)\ x\ (\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {pred} \ (\operatorname {first} \ x))\ (\operatorname {pred} \ (\operatorname {second} \ x)))))}

The recursion may be implemented using the Y combinator,

OneZ=λc.λx.IsZero (first x) x (IsZero (second x) x (c (pair (pred (first x)) (pred (second x))))){\displaystyle \operatorname {OneZ} =\lambda c.\lambda x.\operatorname {IsZero} \ (\operatorname {first} \ x)\ x\ (\operatorname {IsZero} \ (\operatorname {second} \ x)\ x\ (c\ (\operatorname {pair} \ (\operatorname {pred} \ (\operatorname {first} \ x))\ (\operatorname {pred} \ (\operatorname {second} \ x)))))}
OneZero=YOneZ{\displaystyle \operatorname {OneZero} =Y\operatorname {OneZ} }

Plus and minus

[edit]

Addition is defined mathematically on the pair by,

x+y=[xp,xn]+[yp,yn]=xpxn+ypyn=(xp+yp)(xn+yn)=[xp+yp,xn+yn]{\displaystyle x+y=[x_{p},x_{n}]+[y_{p},y_{n}]=x_{p}-x_{n}+y_{p}-y_{n}=(x_{p}+y_{p})-(x_{n}+y_{n})=[x_{p}+y_{p},x_{n}+y_{n}]}

The last expression is translated into lambda calculus as,

pluss=λx.λy.OneZero (pair (plus (first x) (first y)) (plus (second x) (second y))){\displaystyle \operatorname {plus} _{s}=\lambda x.\lambda y.\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {plus} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))}

Similarly subtraction is defined,

xy=[xp,xn][yp,yn]=xpxnyp+yn=(xp+yn)(xn+yp)=[xp+yn,xn+yp]{\displaystyle x-y=[x_{p},x_{n}]-[y_{p},y_{n}]=x_{p}-x_{n}-y_{p}+y_{n}=(x_{p}+y_{n})-(x_{n}+y_{p})=[x_{p}+y_{n},x_{n}+y_{p}]}

giving,

minuss=λx.λy.OneZero (pair (plus (first x) (second y)) (plus (second x) (first y))){\displaystyle \operatorname {minus} _{s}=\lambda x.\lambda y.\operatorname {OneZero} \ (\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {plus} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}

Multiply and divide

[edit]

Multiplication may be defined by,

xy=[xp,xn][yp,yn]=(xpxn)(ypyn)=(xpyp+xnyn)(xpyn+xnyp)=[xpyp+xnyn,xpyn+xnyp]{\displaystyle x*y=[x_{p},x_{n}]*[y_{p},y_{n}]=(x_{p}-x_{n})*(y_{p}-y_{n})=(x_{p}*y_{p}+x_{n}*y_{n})-(x_{p}*y_{n}+x_{n}*y_{p})=[x_{p}*y_{p}+x_{n}*y_{n},x_{p}*y_{n}+x_{n}*y_{p}]}

The last expression is translated into lambda calculus as,

mults=λx.λy.pair (plus (mult (first x) (first y)) (mult (second x) (second y))) (plus (mult (first x) (second y)) (mult (second x) (first y))){\displaystyle \operatorname {mult} _{s}=\lambda x.\lambda y.\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {mult} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {mult} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))\ (\operatorname {plus} \ (\operatorname {mult} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {mult} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}

A similar definition is given here for division, except in this definition, one value in each pair must be zero (seeOneZero above). ThedivZ function allows us to ignore the value that has a zero component.

divZ=λx.λy.IsZero y 0 (divide x y){\displaystyle \operatorname {divZ} =\lambda x.\lambda y.\operatorname {IsZero} \ y\ 0\ (\operatorname {divide} \ x\ y)}

divZ is then used in the following formula, which is the same as for multiplication, but withmult replaced bydivZ.

divides=λx.λy.pair (plus (divZ (first x) (first y)) (divZ (second x) (second y))) (plus (divZ (first x) (second y)) (divZ (second x) (first y))){\displaystyle \operatorname {divide} _{s}=\lambda x.\lambda y.\operatorname {pair} \ (\operatorname {plus} \ (\operatorname {divZ} \ (\operatorname {first} \ x)\ (\operatorname {first} \ y))\ (\operatorname {divZ} \ (\operatorname {second} \ x)\ (\operatorname {second} \ y)))\ (\operatorname {plus} \ (\operatorname {divZ} \ (\operatorname {first} \ x)\ (\operatorname {second} \ y))\ (\operatorname {divZ} \ (\operatorname {second} \ x)\ (\operatorname {first} \ y)))}

Rational and real numbers

[edit]

Rational andcomputable real numbers may also be encoded in lambda calculus. Rational numbers may be encoded as a pair of signed numbers. Computable real numbers may be encoded by a limiting process that guarantees that the difference from the real value differs by a number which may be made as small as we need.[4][5] The references given describe software that could, in theory, be translated into lambda calculus. Once real numbers are defined, complex numbers are naturally encoded as a pair of real numbers.

The data types and functions described above demonstrate that any data type or calculation may be encoded in lambda calculus. This is theChurch–Turing thesis.

List encodings

[edit]

Alist contains some items in order. The basicoperations on lists are:

FunctionDescription
nilConstruct an empty list
isnilTest if list is empty
consPrepend a given value to a (possibly empty) list
headGet the first element of the list
tailGet the rest of the list
singletonCreate a list containing one given element
appendAppend two lists together
foldFold the list with the given "plus" and "zero"

A representation of lists should provide ways to implement these operations.

The archetypal lambda calculus representation of lists is Church List encoding. It represents lists asright folds, as functions to return the results of folding over the list with user-supplied arguments.

It follows the paradigm of "a thing is the result of its observation". No matter the concrete implementation, folding a given list of values results in the same result. This provides an abstract view at what a list is. Church List encoding is such a mechanism.

On the other hand, seen more concretely, lists can be represented as a sequence oflinked listnodes.

What follows are four different representations of lists:

  • Church lists –right fold representation.
  • Two Church pairs for each list node.
  • One Church pair for each list node.
  • Scott encoding.

Church lists –right fold representation

[edit]

This is the original Church encoding for lists. A list is represented by a binary function, that, when supplied with two arguments, – a "combining function" and a "sentinel value", – will perform theright fold of the encoded list using those two arguments.

For an empty list the sentinel value is returned as the folding's result. The result of folding a non-empty list withhead h andtail t is the result of combining, by the supplied function, of thehead h with theresult of folding the tail t with the supplied two arguments. Thus the combining function's two arguments are, conceptually, thecurrent element and theresult of folding therest of the list.

For example, a list of three elements x, y and z is represented by a term that when applied to c and n returns c x (c y (c z n)). Equivalently, it is an application of the chain offunctional compositions ({\displaystyle \circ } ) of partial applications, ((c x){\displaystyle \circ } (c y){\displaystyle \circ } (c z)) n.

nilλcn.nisnilλl.l (λhr.false) trueconsλht.λcn.c h (t c n)singletonλh.λcn.c h nappendλlt.λcn.l c (t c n)nonemptyλl.l (λhr.true) falseheadλl.l (λhr.h) falsesafeHeadλles.l (λhr.s h) efoldλcnl.l c nmapλfl.λcn.l (λhr.c (f h) r) nλflc.l (cf)tailλl.λcn.l (λhrg.g h (r c)) (λg.n) (λht.t){\displaystyle {\begin{aligned}\operatorname {nil} &\equiv \lambda \,c\,n.n\\\operatorname {isnil} &\equiv \lambda \,l.l\ (\lambda \,h\,r.\operatorname {false} )\ \operatorname {true} \\\operatorname {cons} &\equiv \lambda \,h\,t.\lambda \,c\,n.c\ h\ (t\ c\ n)\\\operatorname {singleton} &\equiv \lambda \,h.\lambda \,c\,n.c\ h\ n\\\operatorname {append} &\equiv \lambda \,l\,t.\lambda \,c\,n.l\ c\ (t\ c\ n)\\\operatorname {nonempty} &\equiv \lambda \,l.l\ (\lambda \,h\,r.\operatorname {true} )\ \operatorname {false} \\\operatorname {head} &\equiv \lambda \,l.l\ (\lambda \,h\,r.h)\ \operatorname {false} \\\operatorname {safeHead} &\equiv \lambda \,l\,e\,s.l\ (\lambda \,h\,r.s\ h)\ e\\\operatorname {fold} &\equiv \lambda \,c\,n\,l.l\ c\ n\\\operatorname {map} &\equiv \lambda f\,l.\lambda \,c\,n.l\ (\lambda \,h\,r.c\ (f\ h)\ r)\ n\equiv \lambda f\,l\,c.l\ (c\circ f)\\\operatorname {tail} &\equiv \lambda \,l.\lambda \,c\,n.l\ (\lambda \,h\,r\,g.g\ h\ (r\ c))\ (\lambda \,g.n)\ (\lambda \,h\,t.t)\end{aligned}}}

These definitions follow the following logic: the equations

 fold c n [  ]     =  n fold c n [x ]     =  c x n fold c n [x,y,z]  =  c x (c y (c z n))

mean that

{ [    ] }λcn.n{ [ x   ] }λcn.c x n{ [ x,y,z ] }λcn.c x (c y (c z n)){\displaystyle {\begin{aligned}&\{\ [\ \ \ \ ]\ \}&&\equiv \lambda \,c\,n.n\\&\{\ [\ x\ \ \ ]\ \}&&\equiv \lambda \,c\,n.c\ x\ n\\&\{\ [\ x,\,y,\,z\ ]\ \}&&\equiv \lambda \,c\,n.c\ x\ (c\ y\ (c\ z\ n))\end{aligned}}}

where{ l }=λcn.fold c n l{\displaystyle \{\ l\ \}=\lambda \,c\,n.fold\ c\ n\ l} denotes the Church List representation of the listl{\displaystyle l}.

Since Church encoded list is its own folding function, folding it just means applying that function to the supplied arguments.

This list representation can be given type inSystem F.

The evident correspondence to Church numerals is non-coincidental, as that can be seen as a unary encoding, with natural numbers represented by lists of unit (i.e. non-important) values, e.g. [() () ()], with the list's length serving as the representation of the natural number. Right folding over such lists uses functions which necessarily ignore the element's value, and is equivalent to the chained functional composition, i.e. ( (c ()){\displaystyle \circ } (c ()){\displaystyle \circ } (c ()) ) n = (f{\displaystyle \circ } f{\displaystyle \circ } f) n, as is used in Church numerals.

Two pairs as a list node

[edit]

A nonempty list can be represented by a Church pair, where

  • first contains the list's head
  • second contains the list's tail

However this does not give a representation of the empty list, because there is no "null" pointer. To represent null, the pair can be wrapped in another pair, giving three values:

  • first - the null list indicator (a Boolean).
  • first of second contains the head (car).
  • second of second contains the tail (cdr).

Using this idea the basic list operations can be defined like this:[6]

ExpressionDescription
nilpair true true{\displaystyle \operatorname {nil} \equiv \operatorname {pair} \ \operatorname {true} \ \operatorname {true} }The first element of the pair istrue meaning the list is null.
isnilfirst{\displaystyle \operatorname {isnil} \equiv \operatorname {first} }Retrieve the null (or empty list) indicator.
consλh.λt.pairfalse (pairh t){\displaystyle \operatorname {cons} \equiv \lambda h.\lambda t.\operatorname {pair} \operatorname {false} \ (\operatorname {pair} h\ t)}Create a list node, which is not null, and give it a headh and a tailt.
headλz.first (secondz){\displaystyle \operatorname {head} \equiv \lambda z.\operatorname {first} \ (\operatorname {second} z)}second.first is the head.
tailλz.second (secondz){\displaystyle \operatorname {tail} \equiv \lambda z.\operatorname {second} \ (\operatorname {second} z)}second.second is the tail.

In anil nodesecond is never accessed, provided thathead andtail are only applied to nonempty lists.

One pair as a list node

[edit]

Alternatively, define[7]

conspairheadλl. l (λhtd. h) niltailλl. l (λhtd. t) nilnilfalseisnilλl.l (λhtd.false)true{\displaystyle {\begin{aligned}\operatorname {cons} &\equiv \operatorname {pair} \\\operatorname {head} &\equiv \lambda l.\ l\ (\lambda htd.\ h)\ \operatorname {nil} \\\operatorname {tail} &\equiv \lambda l.\ l\ (\lambda htd.\ t)\ \operatorname {nil} \\\operatorname {nil} &\equiv \operatorname {false} \\\operatorname {isnil} &\equiv \lambda l.l\ (\lambda htd.\operatorname {false} )\operatorname {true} \\\end{aligned}}}

where the definitions like the last one all follow the same general pattern for the safe use of a list, withh{\displaystyle h} andt{\displaystyle t} referring to the list's head and tail, andd{\displaystyle d} being discarded, as an artificial device:

λl.l (λhtd.head-and-tail-clause) nil-clause{\displaystyle {\begin{aligned}\lambda l.l\ (\lambda htd.\langle \operatorname {head-and-tail-clause} \rangle )\ \langle \operatorname {nil-clause} \rangle \\\end{aligned}}}

Other operations in this encoding are:

lfoldλf. Y (λr.λal. l (λhtd. r (f a h) t) a)rfoldλfa. Y (λr.λl. l (λhtd. f (r t) h) a)lengthlfold (λah. succ a) zero{\displaystyle {\begin{aligned}\operatorname {lfold} &\equiv \lambda f.\ \operatorname {Y} \ (\lambda r.\lambda al.\ l\ (\lambda htd.\ r\ (f\ a\ h)\ t)\ a)\\\operatorname {rfold} &\equiv \lambda fa.\ \operatorname {Y} \ (\lambda r.\lambda l.\ l\ (\lambda htd.\ f\ (r\ t)\ h)\ a)\\\operatorname {length} &\equiv \operatorname {lfold} \ (\lambda ah.\ \operatorname {succ} \ a)\ \operatorname {zero} \end{aligned}}}

mapλf. rfold (λah. cons (f h) a) nilfilterλp. rfold (λah. p h (cons h a) a) nilreversefold (λah. cons h a) nilconcatλlg. rfold (λah. cons h a) g lconjλlv. concat l (cons v nil){\displaystyle {\begin{aligned}\operatorname {map} &\equiv \lambda f.\ \operatorname {rfold} \ (\lambda ah.\ \operatorname {cons} \ (f\ h)\ a)\ \operatorname {nil} \\\operatorname {filter} &\equiv \lambda p.\ \operatorname {rfold} \ (\lambda ah.\ p\ h\ (\operatorname {cons} \ h\ a)\ a)\ \operatorname {nil} \\\operatorname {reverse} &\equiv \operatorname {fold} \ (\lambda ah.\ \operatorname {cons} \ h\ a)\ \operatorname {nil} \\\operatorname {concat} &\equiv \lambda lg.\ \operatorname {rfold} \ (\lambda ah.\ \operatorname {cons} \ h\ a)\ g\ l\\\operatorname {conj} &\equiv \lambda lv.\ \operatorname {concat} \ l\ (\operatorname {cons} \ v\ \operatorname {nil} )\end{aligned}}}

dropλn. n tailY (λr.λnl. l (λhtd. IsZero n l (r (pred n) t)) nil)drop-lastλnl. IsZero n l second(        Y (λrlr. lr (λhtd.            r t (λnala. IsZero na                    (pair zero (cons h la))                    (pair (pred na) nil) ))            (pair n nil) )         l )drop-whileλp. Y (λrl. l (λhtd. p h (r t) l) nil)takeY (λrnl. l (λhtd. IsZero n nil (cons h (r (pred n) t))) nil)take-lastλnl. IsZero n l second(        Y (λrlr. lr (λhtd.            r t (λnala. IsZero na                    (pair zero la)                    (pair (pred na) lr) ))            (pair n nil) )         l)take-whileλp. Y (λrl. l (λhtd. p h (cons h (r t)) nil) nil){\displaystyle {\begin{aligned}\operatorname {drop} &\equiv \lambda n.\ n\ \operatorname {tail} \\&\equiv \operatorname {Y} \ (\lambda r.\lambda nl.\ l\ (\lambda htd.\ \operatorname {IsZero} \ n\ l\ (r\ (\operatorname {pred} \ n)\ t))\ \operatorname {nil} )\\\operatorname {drop-last} &\equiv \lambda nl.\ \operatorname {IsZero} \ n\ l\ \operatorname {second} (\\&\ \ \ \ \ \ \ \ \operatorname {Y} \ (\lambda rl_{r}.\ l_{r}\ (\lambda htd.\\&\ \ \ \ \ \ \ \ \ \ \ \ r\ t\ (\lambda n_{a}l_{a}.\ \operatorname {IsZero} \ n_{a}\\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ \operatorname {zero} \ (\operatorname {cons} \ h\ l_{a}))\\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ (\operatorname {pred} \ n_{a})\ \operatorname {nil} )\ ))\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ n\ \operatorname {nil} )\ )\\&\ \ \ \ \ \ \ \ \ l\ )\\\operatorname {drop-while} &\equiv \lambda p.\ \operatorname {Y} \ (\lambda rl.\ l\ (\lambda htd.\ p\ h\ (r\ t)\ l)\ \operatorname {nil} )\\\operatorname {take} &\equiv \operatorname {Y} \ (\lambda rnl.\ l\ (\lambda htd.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ h\ (r\ (\operatorname {pred} \ n)\ t)))\ \operatorname {nil} )\\\operatorname {take-last} &\equiv \lambda nl.\ \operatorname {IsZero} \ n\ l\ \operatorname {second} (\\&\ \ \ \ \ \ \ \ \operatorname {Y} \ (\lambda rl_{r}.\ l_{r}\ (\lambda htd.\\&\ \ \ \ \ \ \ \ \ \ \ \ r\ t\ (\lambda n_{a}l_{a}.\ \operatorname {IsZero} \ n_{a}\\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ \operatorname {zero} \ l_{a})\\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ (\operatorname {pred} \ n_{a})\ l_{r})\ ))\\&\ \ \ \ \ \ \ \ \ \ \ \ (\operatorname {pair} \ n\ \operatorname {nil} )\ )\\&\ \ \ \ \ \ \ \ \ l)\\\operatorname {take-while} &\equiv \lambda p.\ \operatorname {Y} \ (\lambda rl.\ l\ (\lambda htd.\ p\ h\ (\operatorname {cons} \ h\ (r\ t))\ \operatorname {nil} )\ \operatorname {nil} )\end{aligned}}}

allY (λrpl. l (λhtd. p h (r p t) false) true)anyY (λrpl. l (λhtd. p h true (r p t)) false)element-atλnl. head (drop n l)insert-atλnvl. concat (take n l) (cons v (drop n l))remove-atλnl. concat (take n l) (drop (succ n) l)replace-atλnvl. concat (take n l) (cons v (drop (succ n) l))index-ofλp. Y (λrnl. l (λhtd. p h n (r (succ n) t)) zero) onelast-index-ofλp. Y (λrnl. l (λhtd. (λi. IsZero i (p h n zero) i) (r (succ n) t)) zero) onerangeλfz. Y (λrsn. IsZero n nil (cons (s f z) (r (succ s) (pred n)))) zerorepeatλv. Y (λrn. IsZero n nil (cons v (r (pred n))))zipY (λrl1l2. l1 (λh1t1d1. l2 (λh2t2d2. cons (pair h1 h2) (r t1 t2)) nil) nil){\displaystyle {\begin{aligned}\operatorname {all} &\equiv \operatorname {Y} \ (\lambda rpl.\ l\ (\lambda htd.\ p\ h\ (r\ p\ t)\ \operatorname {false} )\ \operatorname {true} )\\\operatorname {any} &\equiv \operatorname {Y} \ (\lambda rpl.\ l\ (\lambda htd.\ p\ h\ \operatorname {true} \ (r\ p\ t))\ \operatorname {false} )\\\operatorname {element-at} &\equiv \lambda nl.\ \operatorname {head} \ (\operatorname {drop} \ n\ l)\\\operatorname {insert-at} &\equiv \lambda nvl.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {cons} \ v\ (\operatorname {drop} \ n\ l))\\\operatorname {remove-at} &\equiv \lambda nl.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {drop} \ (\operatorname {succ} \ n)\ l)\\\operatorname {replace-at} &\equiv \lambda nvl.\ \operatorname {concat} \ (\operatorname {take} \ n\ l)\ (\operatorname {cons} \ v\ (\operatorname {drop} \ (\operatorname {succ} \ n)\ l))\\\operatorname {index-of} &\equiv \lambda p.\ \operatorname {Y} \ (\lambda rnl.\ l\ (\lambda htd.\ p\ h\ n\ (r\ (\operatorname {succ} \ n)\ t))\ \operatorname {zero} )\ \operatorname {one} \\\operatorname {last-index-of} &\equiv \lambda p.\ \operatorname {Y} \ (\lambda rnl.\ l\ (\lambda htd.\ (\lambda i.\ \operatorname {IsZero} \ i\ (p\ h\ n\ \operatorname {zero} )\ i)\ (r\ (\operatorname {succ} \ n)\ t))\ \operatorname {zero} )\ \operatorname {one} \\\operatorname {range} &\equiv \lambda fz.\ \operatorname {Y} \ (\lambda rsn.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ (s\ f\ z)\ (r\ (\operatorname {succ} \ s)\ (\operatorname {pred} \ n))))\ \operatorname {zero} \\\operatorname {repeat} &\equiv \lambda v.\ \operatorname {Y} \ (\lambda rn.\ \operatorname {IsZero} \ n\ \operatorname {nil} \ (\operatorname {cons} \ v\ (r\ (\operatorname {pred} \ n))))\\\operatorname {zip} &\equiv Y\ (\lambda rl_{1}l_{2}.\ l_{1}\ (\lambda h_{1}t_{1}d_{1}.\ l_{2}\ (\lambda h_{2}t_{2}d_{2}.\ \operatorname {cons} \ (\operatorname {pair} \ h_{1}\ h_{2})\ (r\ t_{1}\ t_{2}))\ \operatorname {nil} )\ \operatorname {nil} )\\\end{aligned}}}

Scott lists

[edit]

Scott encoding for data types follows their surface syntax without regard to recursion. In the disjunction of conjunctions a.k.a. sum of products style of data type definitions, it represents a datum as a function which expects as many arguments as there are alternatives in its data type definition, where each such argument is expected to be a "handler" function that must be able to handle a given number of data arguments that will correspond to the data fields for that alternative.

For lists, it means the data type definition of

List:=NIL |ConsvalList{\displaystyle \qquad List:=\operatorname {NIL} \ |\,\operatorname {Cons} \,\langle val\rangle \,List}

and lists being represented as

NIL=λnc.nCons=λad.λnc.c a dIsEmpty=λl.ltrue(λad.false)Head=λl.lNIL(λad.a)Tail=λl.lNIL(λad.d)fold=λgz.Yλrl.l z (λad.ga (r d))Append=foldConsMap=λf.fold(λh.Cons(fh))NILMap2=λf.Yλrpq.pNIL(λad.                 qNIL(λbg.Cons(fab)(r d g))){\displaystyle \quad {\begin{aligned}\operatorname {NIL} &=\lambda nc.n\\\operatorname {Cons} &=\lambda ad.\lambda nc.c\ a\ d\\\operatorname {IsEmpty} &=\lambda l.l\,\operatorname {true} \,(\lambda ad.\operatorname {false} )\\\operatorname {Head} &=\lambda l.l\,\operatorname {NIL} \,(\lambda ad.a)\\\operatorname {Tail} &=\lambda l.l\,\operatorname {NIL} \,(\lambda ad.d)\\\operatorname {fold} &=\lambda gz.\operatorname {Y} \lambda rl.l\ z\ (\lambda ad.g\,a\ (r\ d))\\\operatorname {Append} &=\operatorname {fold} \,\operatorname {Cons} \\\operatorname {Map} &=\lambda f.\operatorname {fold} \,(\lambda h.\operatorname {Cons} \,(f\,h))\,\operatorname {NIL} \\\operatorname {Map2} &=\lambda f.\operatorname {Y} \lambda rpq.p\,\operatorname {NIL} \,(\lambda ad.\\&\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ q\,\operatorname {NIL} \,(\lambda bg.\operatorname {Cons} \,(f\,a\,b)(r\ d\ g)))\\\end{aligned}}}

Recursive operations on Scott lists typically require explicit use of recursion, e.g. usingY{\displaystyle \operatorname {Y} } combinator, or explicit self-application definitions. One such example isfold, unlike the no-op that it is under Church encoding. Buttail is immediately available, so its definition is much simpler here, in comparison. SeeScott encoding for more.

Scott encoding can be seen as using the idea ofcontinuations, which can lead to simpler code[8]. In this approach, we use the fact that lists can be observed usingpattern matching expression. For example, usingScala notation, iflist denotes a value of typeList with empty listNil and constructorCons(h, t) we can inspect the list and computenilCode in case the list is empty andconsCode(h, t) when the list is not empty:

listmatch{caseNil=>nilCodecaseCons(h,t)=>consCode(h,t)}

Thelist is given by how it acts uponnilCode andconsCode. We therefore define a list as a function that accepts suchnilCode andconsCode as arguments, so that instead of the above pattern match we may simply write:

list nilCode consCode{\displaystyle \operatorname {list} \ \operatorname {nilCode} \ \operatorname {consCode} }

Let us denote byn the parameter corresponding tonilCode and byc the parameter corresponding toconsCode.The empty list is the one that returns the nil argument:

nilλn.λc. n{\displaystyle \operatorname {nil} \equiv \lambda n.\lambda c.\ n}

The non-empty list with headh and tailt is given by

cons h t    λn.λc. c h t{\displaystyle \operatorname {cons} \ h\ t\ \ \equiv \ \ \lambda n.\lambda c.\ c\ h\ t}

More generally, analgebraic data type withm{\displaystyle m} alternatives becomes a function withm{\displaystyle m} parameters. When thei{\displaystyle i}th constructor hasni{\displaystyle n_{i}} arguments, the corresponding parameter of the encoding takesni{\displaystyle n_{i}} arguments as well.

Scott encoding can be done in untyped lambda calculus, whereas its use with types requires a type system with recursion and type polymorphism. A list with element type E in this representation that is used to compute values of type C would have the following recursive type definition, where '=>' denotesfunction type:

typeList=C=>// nil argument(E=>List=>C)=>// cons argumentC// result of pattern matching

A list that can be used to compute arbitrary types would have a type that quantifies overC. A list generic[clarification needed] inE would also takeE as the type argument.

General Remarks

[edit]

A straightforward implementation of Church encoding slows some access operations fromO(1){\displaystyle O(1)} toO(n){\displaystyle O(n)}, wheren{\displaystyle n} is the size of thedata structure, making Church encoding impractical.[9] Research has shown that this can be addressed by targeted optimizations, but mostfunctional programming languages instead expand their intermediate representations to containalgebraic data types.[10] Nonetheless Church encoding is often used in theoretical arguments, as it is a natural representation for partial evaluation and theorem proving.[9] Operations can be typed usinghigher-ranked types,[11] and primitive recursion is easily accessible.[9] The assumption that functions are the only primitive data types streamlines many proofs.

Church encoding is complete but only representationally. Additional functions are needed to translate the representation into common data types, for display to people. It is not possible in general to decide if two functions areextensionally equal due to theundecidability of equivalence fromChurch's theorem. The translation may apply the function in some way to retrieve the value it represents, or look up its value as a literal lambda term. Lambda calculus is usually interpreted as usingintensional equality. There arepotential problems with the interpretation of results because of the difference between the intensional and extensional definition of equality.

See also

[edit]

References

[edit]
  1. ^Jansen, Jan Martin (2013), "Programming in the λ-calculus: from Church to Scott and back",The Beauty of Functional Code, Lecture Notes in Computer Science, vol. 8106, Springer-Verlag, pp. 168–180,doi:10.1007/978-3-642-40355-2_12,ISBN 978-3-642-40354-5.
  2. ^Allison, Lloyd."Lambda Calculus Integers".
  3. ^Bauer, Andrej."Andrej's answer to a question; "Representing negative and complex numbers using lambda calculus"".
  4. ^"Exact real arithmetic".Haskell.Archived from the original on 2015-03-26.
  5. ^Bauer, Andrej (26 September 2022)."Real number computational software".GitHub.
  6. ^Pierce, Benjamin C. (2002).Types and Programming Languages.MIT Press. p. 500.ISBN 978-0-262-16209-8.
  7. ^Tromp, John (2007)."14. Binary Lambda Calculus and Combinatory Logic". In Calude, Cristian S (ed.).Randomness And Complexity, From Leibniz To Chaitin. World Scientific. pp. 237–262.ISBN 978-981-4474-39-9.
    As PDF:Tromp, John (14 May 2014)."Binary Lambda Calculus and Combinatory Logic"(PDF). Retrieved2017-11-24.
  8. ^Jansen, Jan Martin (2013). "Programming in the λ-Calculus: From Church to Scott and Back". In Achten, Peter; Koopman, Pieter W. M. (eds.).The Beauty of Functional Code - Essays Dedicated to Rinus Plasmeijer on the Occasion of His 61st Birthday. Lecture Notes in Computer Science. Vol. 8106. Springer. pp. 168–180.doi:10.1007/978-3-642-40355-2_12.ISBN 978-3-642-40354-5.
  9. ^abcTrancón y Widemann, Baltasar; Parnas, David Lorge (2008). "Tabular Expressions and Total Functional Programming". In Olaf Chitil; Zoltán Horváth; Viktória Zsók (eds.).Implementation and Application of Functional Languages. 19th International Workshop, IFL 2007, Freiburg, Germany, September 27–29, 2007 Revised Selected Papers. Lecture Notes in Computer Science. Vol. 5083. pp. 228–229.doi:10.1007/978-3-540-85373-2_13.ISBN 978-3-540-85372-5.
  10. ^Jansen, Jan Martin; Koopman, Pieter W. M.; Plasmeijer, Marinus J. (2006). "Efficient interpretation by transforming data types and patterns to functions". In Nilsson, Henrik (ed.).Trends in functional programming. Volume 7. Bristol: Intellect. pp. 73–90.CiteSeerX 10.1.1.73.9841.ISBN 978-1-84150-188-8.
  11. ^"Predecessor and lists are not representable in simply typed lambda calculus".Lambda Calculus and Lambda Calculators. okmij.org.
General
Theorems
(list),
paradoxes
Logics
Traditional
Propositional
Predicate
Set theory
Types
ofsets
Maps,
cardinality
Theories
Formal
systems

(list),
language,
syntax
Example
axiomatic
systems

(list)
Proof theory
Model theory
Computability
theory
Related
Notable ideas
Students
Institutions
Family
Retrieved from "https://en.wikipedia.org/w/index.php?title=Church_encoding&oldid=1337642791"
Category:
Hidden categories:

[8]ページ先頭

©2009-2026 Movatter.jp