Church numerals: How should I interpret the numbers from expressions? - lambda-calculus

Can someone explain to me using substitutions how we get a number "zero" or the rest of natural numbers?
For example the value: "zero"
λf.λx.x
if I apply this expression on an another expression:
"(λf.(λx.x)) a"
then using substitution:
:=[a/f](λx.x)
:=(λx.x)
what am I missing? How should I interpret these number expressions?

The church numeral n is a function that takes another function f and returns a function that applies f to its argument n times. So 0 a (where 0 is, as you said, λf.λx.x
) returns λx.x because that applies a to x 0 times.
1 a gives you λx. a x, 2 a gives you λx. a (a x) and so on.

Below is the explanation based on paper by Erhan Bagdemir in the comment to answer by sepp2k.
Essential points to grasp:
all Church numerals are functions of two parameters;
for Church numerals, it is implied that:
f — is the 'successor' function (i.e. function which accepts a Church numeral and return church numeral next one, it's basically and increment);
x — is a (Church numeral) value representing 'zero' (the count starting point).
Keeping that in mind:
λf . λx . x
will be equal to zero, if we will pass the appropriate f (in this particular case it doesn't matter what function will be passed as f, since it never applied) and x:
λf . λx . ZERO
following:
λf . λx . fx
will be evaluated to 1:
λf . λx . INCREMENT ZERO
and this:
λf . λx . f f x
will be qual to 2:
λf . λx . INCREMENT(INCREMENT ZERO)
and so on, for all the successive numbers.
See my (broader) answer to another (but closely related) question.

A church numeral n, (say 2,) represents the "action" of applying any given function n times (here,two times) on any given parameter.
A church numeral, by definition, is a function that takes two parameters, namely
1) a function
2) a parameter or expression or value on which the supplied function is applied.
When the supplied function is the successor function, and the supplied second parameter is Zero , you get the numeral. (2, in the above example)
Church numeral 2 is by definition,
λf . λx . f( f( x))
,Which is obviously a function that takes two parameters.
On passing the successor function, i.e f(x)=x+1 as first parameter and zero as second parameter to the function, we get...
f(f(0))
=f(1)
=2
This explanation is kinda simplified as definition of successor function and zero aren't as shown, in lambda calculus..
Refer :http://www.cse.unt.edu/~tarau/teaching/GPL/docs/Church%20encoding.pdf
An excellent explanation on church encodings

Related

Prolog pattern matching function with n arguments

I want to know how to do a pattern matching of a function that can take n arguments in prolog for example :
cons(1,2) should return [1,2],cons (1,2,3) should return [1,2,3]and(cons(1,2,3,....,n)) returns [1,2,3,....,n]
so cons can have as many arguments as it wants
and the only thing i could think if is
match(cons(A,B),[A,B]).but that just works with 2 arguments , so i want to generalize it for n arguments .

Why the definition of Church's Numerals

I want to understand, why Church define the numerals like:
0 = λ f . λ x . x
1 = λ f . λ x . f x
2 = λ f . λ x . f f x
3 = λ f . λ x . f f f x
4 = λ f . λ x . f f f f x
What is the logic behind?
Why 0 is represent like:
0 = λ f . λ x . x
Church wasn't trying to be practical. He was trying to prove results about the expressive power of lambda calculus — that in principle any possible computation can be done in lambda calculus, hence lambda calculus can serve as a theoretical foundation for the study of computability. In order to do so, it was necessary to encode numbers as lambda expressions, in such a way that things like the successor function are easily definable. This was a key step in showing the equivalence of lambda calculus and Gödel's recursive function theory (which was about computable functions on the natural numbers). Church numerals are basically a convenient albeit not very readable encoding of numbers. In some sense, there isn't any very deep logic to it. The claim isn't that 1 in its essence is λ f . λ x . f x, but that the latter is a serviceable encoding of the former.
This doesn't mean that it is an arbitrary encoding. There is a definite logic to it. The most natural way to encode a number n is by something which involves n. Church numerals use n function applications. The natural number n is represented by the higher order function which applies a function n times to an input. 1 is encoded by a function applied once, 2 by a function applied twice and so on. It is a very natural encoding, especially in the context of lambda calculus. Furthermore, the fact that it is easy to define arithmetic on them streamlines the proof that lambda calculus is equivalent to recursive functions.
To see this in practice, you can run the following Python3 script:
#some Church numerals:
ZERO = lambda f: lambda x: x
ONE = lambda f: lambda x: f(x)
TWO = lambda f: lambda x: f(f(x))
THREE = lambda f: lambda x: f(f(f(x)))
#function to apply these numerals to:
def square(x): return x**2
#so ZERO(square), ONE(square), etc. are functions
#apply these to 2 and print the results:
print(ZERO(square)(2), ONE(square)(2), TWO(square)(2),THREE(square)(2))
Output:
2 4 16 256
Note that these numbers have been obtained by squaring the number two 0 times, 1 times, 2 times, and 3 times respectively.
According to the Peano axioms, a natural number is either 0 or S(n) for another natural number n:
0 = 0
1 = S(0)
2 = S(S(0))
...
You can see Church numerals as a generalization of Peano numbers, where you provide your own 0 and S:
0 = λs.λz. z
1 = λs.λz. s(z)
2 = λs.λz. s(s(z))
...
Since this is a programming forum, let's create some Church numerals in EcmaScript 6:
const ZERO = s => z => z;
const ONE = s => z => s(z);
const TWO = s => z => s(s(z));
...
You can convert these Church numerals to JavaScript numbers by providing the appropriate zero and successor:
function toInt(n) {
return n(i => i + 1)(0);
}
And then:
> toInt(TWO)
2
You could use Church numerals to do some practical things:
function shout(text) {
return text + "!";
}
> shout("hi")
"hi!"
> NINE(shout)("hi")
"hi!!!!!!!!!"
​
You can try it here: https://es6console.com/iyoim5y8/
The following paper by Robert (Corky) Cartwright broke it down for me very well.
Essential points to grasp, for the very beginning:
all Church numerals are functions with two parameters;
in the Church representation of any number, it is implied that:
f — is the 'successor' function (i.e. function which accepts a Church numeral and returns church numeral next to the passed one, it's basically and increment);
x — is a (Church numeral) value representing 'zero' (the count starting point).
Keeping that in mind:
λf . λx . x
will be equal to zero, if we will pass the appropriate f ('successor' —increment function) and x ('zero' — count starting point). In this particular case it doesn't matter what function will be passed as f, since it never applied:
λf . λx . ZERO
this:
λf . λx . fx
will be evaluated to 1:
λf . λx . INCREMENT ZERO
and the following:
λf . λx . f f x
will be qual to 2:
λf . λx . INCREMENT(INCREMENT ZERO)
and so on, for all the successive numbers.
Bonus (addition, multiplication and exponentiation of Church numerals):
Here is a Python code snippet to illustrate (and expand on) said above:
ZERO = lambda f: lambda x: x
ONE = lambda f: lambda x: f(x)
TWO = lambda f: lambda x: f(f(x))
THREE = lambda f: lambda x: f(f(f(x)))
SUCC = lambda x: x + 1
ADD = lambda f: lambda x: lambda n: lambda m: n(f)(m(f)(x))
MULT = lambda f: lambda x: lambda n: lambda m: n(m(f))(x)
EXPON = lambda m: lambda n: n(m)
ADD exploits the fact that any Church numeral accepts a 'zero' count starting point, as it's argument — it just counts to n starting with m. So, ADD(SUCC)(0)(THREE)(TWO) will just count to 3, but starting with 2, thus giving us 2 + 1 + 1 + 1 = 5.
MULT utilizes the fact that a 'successor' function is just an argument of a Church numeral, and thus could be replaced. Thus MULT(SUCC)(0)(TWO)(THREE) will return 3 twice, which is the same as 2 * 3 = 6.
EXPON is a bit tricky (it was for myself, at least), the key point here is to keep track of what is getting returned by what. What it, basically, does — is uses the intrinsic mechanism of Church numerals representation (recursion of f application, in particular). Here are some examples to illustrate:
30
EXPON(THREE)(ZERO)(SUCC)(0)
↓
lambda n: n(THREE)(ZERO)(SUCC)(0)
↓
ZERO(THREE)(SUCC)(0)
↓
lambda x: (SUCC)(0)
↓
SUCC(0)
↓
1
31
EXPON(THREE)(ONE)(SUCC)(0)
↓
lambda n: n(THREE)(ONE)(SUCC)(0)
↓
ONE(THREE)(SUCC)(0)
↓
lambda x: THREE(x)(SUCC)(0)
↓
THREE(SUCC)(0)
↓
3
13
EXPON(ONE)(THREE)(SUCC)(0)
↓
lambda n: n(ONE)(THREE)(SUCC)(0)
↓
THREE(ONE)(SUCC)(0)
↓
lambda x: ONE(ONE(ONE(x)))(SUCC)(0)
↓
ONE(ONE(ONE(SUCC)))(0)
↓
ONE(ONE(lambda x: SUCC(x)))(0)
↓
lambda x:(lambda x: (lambda x: SUCC(x)) (x))(x)(0)
↓
SUCC(0)
↓
1

can't deduce the numeral representation (church encoding) of a lambda expression λx.λy.x(xy)

I have a lambda expression: λx.λy.x(xy), and I'm supposed to infer the integer representation of it. I've read a lot about Church encodings and Church numerals specifically but I can't find what number is. Can you explain it to me in a way a 3 year old can understand or refer me to a resource better than wikipedia?
Church encoding of integers is the following:
"0" ≡ (λf.(λx.x)): Think of (λf.(λx.x)) as meaning: given a function f and an element x, the result is x: it's like applying the function f zero times to x.
"1" ≡ (λf.(λx.(fx))): Think of (λf.(λx.(fx))) as meaning: given a function f and an element x, the result is (fx): which should be thought of as apply f to x or, in more standard mathematical notation, like f(x).
"2" ≡ (λf.(λx.(f(fx)))): Think of (λf.(λx.(f(fx)))) as meaning: given a function f and an element x, the result is (f(fx)): which should be thought of as apply f to x twice or, in more standard mathematical notation, like f(f(x)).
"3" ≡ (λf.(λx.(f(f(fx))))): Think of (λf.(λx.(f(f(fx))))) as meaning: given a function f and an element x, the result is (f(f(fx))): which should be thought of as apply f to x three times or, in more standard mathematical notation, like f(f(f(x))).
I hope that you see the pattern (and the logic behind). In your case, (λx.(λy.(x(xy)))) is the Church encoding of the number 2 (using alpha-equivalence, of course).
The wikiped article is actually quite clear. What is it that you don't understand?

how to Implement in Scheme this function

The Maple computer algeba system has a command seq(f, i = m..n, step), which returns the sequence fm,...fn, where fi is the expression f with all occurrences of the symbol i replaced by the numeric value of i in the sequence of integers from m to n. Implement a scheme function (seq f (start step end)), and produces a list of values (f(start),f(start+step),...,f(start+n*step)), where n is the largest integer such that start+n*step <= end and start+(n+1)*step > end.
I thought this would work: (seq (lambda (x) (* x x)) '(0 2 7)) => (0 4 16 36)
The basic solution to this is to implement iota and map, and combine the two:
iota generates a list of numbers given the start, stop, and step
map invokes a given function on all the elements of the given list, and returns a new list containing the returned values
You have to write those functions, but once you have, your seq function is a simple matter of piecing the two together.

Problem understanding treesort in Haskell

I am trying to figure out how exactly does treesort from here work (I understand flatten, insert and foldr).
I suppose what's being done in treesort is applying insert for each element on the list thus generating a tree and then flattening it. The only problem I can't overcome here is where the list (that is the argument of the function) is hiding (because it is not written anywhere as an argument except for the function type declaration).
One more thing: since dot operator is function composition, why is it an error when I change: treesort = flatten . foldr insert Leaf to treesort = flatten( foldr insert Leaf )?
what's being done in treesort is applying insert for each element on the list thus generating a tree and then flattening it.
Exactly right.
[Where is the list hiding?]
In a functional language, you don't have to give the arguments of a value of function type. For example if I write
f = concat . map (map toUpper)
I get a function of type [[Char]] -> [Char]. This
function expects an argument even though there's no argument in the defining equation.
It's exactly the same as if I had written
f strings = (concat . map (map toUpper)) strings
Since the dot operator is function composition, why is it wrong to change f . g to f (g)?
They don't mean the same thing. What happens when each is applied to x?
(f . g) x = f (g x)
(f (g)) x = (f g) x
You can see the applications associate differently, and f. g is different from f g.
It's a type error because foldr insert Leaf is a function from lists to trees, and flatten is meant to be applied to a single tree, not to a function.
To answer your last question first, you're getting an error because . is a function composition operator that takes two functions (in this case flatten and foldr insert Leaf). If you want to rewrite the code without the use of ., you'll need to create a function that takes some parameter:
-- // Pass the 'list' to the first function and the
-- // result of the call to the second function
treesort list = flatten (foldr insert Leaf list)
This also explains where the list parameter was hiding. When composing functions, you don't need to write parameters explicitly, because the result of the expression f . g is a function that takes some parameter, calls g and then calls f:
-- // function composition..
composed = f . g
-- // ..is equivalent to declaring a function:
composed x = f (g x)
Sometimes, as long as you are not familiar with the pointless style, it is useful to do epsilon-conversion mentally.
If f is an expression with function type, then one can convert it to
\e -> (f) e
And, if we have a definition like
a = \e -> (f) e
we can always safely rewrite it as
a e = (f) e
Thus
treesort = flatten . foldr insert Leaf
is the same as
treesort list = (flatten . foldr insert Leaf) list

Resources