Query on Booleans in Lambda Calculus
To understand how to represent Booleans in lambda calculus, it helps to think about an IF expression, "if a then b else c". This is an expression which chooses the first branch, b, if it is true, and the second, c, if it is false. Lambda expressions can do that very easily:
lambda(x).lambda(y).x
will give you the first of its arguments, and
lambda(x).lambda(y).y
gives you the second. So if a is one of those expressions, then
a b c
gives either b
or c
, which is just what we want the IF to do. So define
true = lambda(x).lambda(y).x
false = lambda(x).lambda(y).y
and a b c
will behave like if a then b else c
.
Looking inside your expression at (n a b)
, that means if n then a else b
.
Then m (n a b) b
means
if m then (if n then a else b) else b
This expression evaluates to a
if both m
and n
are true
, and to b
otherwise. Since a
is the first argument of your function and b
is the second, and true
has been defined as a function that gives the first of its two arguments, then if m
and n
are both true
, so is the whole expression. Otherwise it is false
. And that's just the definition of and
!
All this was invented by Alonzo Church, who invented the lambda calculus.
In the lambda calculus, a Boolean is represented by a function that takes two arguments, one for success and one for failure. The arguments are called continuations, because they continue with the rest of the computation; the boolean True calls the success continuation and the Boolean False calls the failure continuation. This coding is called the Church encoding, and the idea is that a Boolean is very much like an "if-then-else function".
So we can say
true = \s.\f.s
false = \s.\f.f
where s
stands for success, f
stands for failure, and the backslash is an ASCII lambda.
Now I hope you can see where this is going. How do we code and
? Well, in C we could expand it to
n && m = n ? m : false
Only these are functions, so
(n && m) s f = (n ? m : false) s f = n ? (m s f) : (false s f) = n ? (m s f) : f
BUT, the ternary construct, when coded in the lambda calculus, is just function application, so we have
(n && m) s f = (n m false) s f = n (m s f) (false s f) = n (m s f) f
So finally we arrive at
&& = \n . \m . \s . \f . n (m s f) f
And if we rename the success and failure continuations to a
and b
we return to your original
&& = \n . \m . \a . \b . n (m a b) b
As with other computations in lambda calculus, especially when using Church encodings, it is often easier to work things out with algebraic laws and equational reasoning, then convert to lambdas at the end.