The SKI basis

The λ-calculus itself can be built on just three of them — S, K and I. In combinatory logic they are taken as primitives:

S\displaystyle \mathrm{S} =λxyz.xz(yz),K\displaystyle = \lambda x\,y\,z.\,x\,z\,(y\,z), \qquad \mathrm{K} =λxy.x,I\displaystyle = \lambda x\,y.\,x, \qquad \mathrm{I} =λx.x\displaystyle = \lambda x.\,x
(1.28)

And I is not even needed as a primitive — it is expressible through S and K:

SKK\displaystyle \mathrm{S}\,\mathrm{K}\,\mathrm{K} =I\displaystyle = \mathrm{I}
(1.29)

Let us substitute and prove the formula — expand SKK\mathrm{S}\,\mathrm{K}\,\mathrm{K} on an arbitrary argument zz using the definitions (1.28):

SKKz  \displaystyle \mathrm{S}\,\mathrm{K}\,\mathrm{K}\,z \; β  Kz(Kz)  \displaystyle \to_\beta\; \mathrm{K}\,z\,(\mathrm{K}\,z) \; β  z  \displaystyle \to_\beta\; z \; =  Iz.\displaystyle =\; \mathrm{I}\,z.

For any zz we get zz — exactly what I\mathrm{I} does, so SKK\mathrm{S}\,\mathrm{K}\,\mathrm{K} =I= \mathrm{I}.

Any λ-term is translated into combinators mechanically. A term is built in three ways — a variable, an application and an abstraction; variables and applications already exist in combinatory logic, but abstraction has to be eliminated. This is done by bracket abstraction — the operation [x]M[x]\,M, “pull the variable xx out of the term MM”. Its result is a combinator term in which xx no longer occurs but which, if given xx back, reduces to MM again. It is defined by the shape of the body MM:

[x]x\displaystyle [x]\,x =I,[x]M\displaystyle = \mathrm{I}, \qquad [x]\,M =KM    (xFV(M)),[x](MN)\displaystyle = \mathrm{K}\,M \;\;(x \notin \mathrm{FV}(M)), \qquad [x]\,(M\,N) =S([x]M)([x]N)\displaystyle = \mathrm{S}\,([x]\,M)\,([x]\,N)
(1.30)
  • [x]x[x]\,x =I= \mathrm{I}: the body is xx itself; returning the argument unchanged is exactly what I\mathrm{I} does.
  • [x]M[x]\,M =KM= \mathrm{K}\,M when xx FV(M)\notin \mathrm{FV}(M): the body does not depend on xx, so the given argument is simply discarded.
  • [x](MN)[x]\,(M\,N) =S([x]M)([x]N)= \mathrm{S}\,([x]\,M)\,([x]\,N): in an application xx may hide in both MM and NN, so the argument must be handed to both — which is exactly what S\mathrm{S} does.

If the body is itself an abstraction λy.M\lambda y.\,M, the inner variable is removed first and the outer one after: [x](λy.M)[x]\,(\lambda y.\,M) =[x]([y]M)= [x]\,([y]\,M); thus nested λ\lambda are stripped from the inside out until only variables and applications remain.

Take λx.fxx\lambda x.\,f\,x\,x. The body fxxf\,x\,x is an application (fx)x(f\,x)\,x, so we unwind it with the application rule, reducing everything to S\mathrm{S}, K\mathrm{K}, I\mathrm{I}:

[x](fxx)\displaystyle [x]\,(f\,x\,x) =S([x](fx))([x]x)\displaystyle = \mathrm{S}\,([x]\,(f\,x))\,([x]\,x) =S(S([x]f)([x]x))I\displaystyle = \mathrm{S}\,\bigl(\mathrm{S}\,([x]\,f)\,([x]\,x)\bigr)\,\mathrm{I} =S(S(Kf)I)I\displaystyle = \mathrm{S}\,(\mathrm{S}\,(\mathrm{K}\,f)\,\mathrm{I})\,\mathrm{I}

There are no variables in the result — only S\mathrm{S}, K\mathrm{K}, I\mathrm{I} and the free ff: λx.fxx  \lambda x.\,f\,x\,x \;   S(S(Kf)I)I\rightsquigarrow\; \mathrm{S}\,(\mathrm{S}\,(\mathrm{K}\,f)\,\mathrm{I})\,\mathrm{I}.