top | item 39481720

Fixed-point combinator

54 points| tosh | 2 years ago |en.wikipedia.org | reply

26 comments

order
[+] ridiculous_fish|2 years ago|reply
I have no background in combinatory logic, and so I've predictably never understood fixed-point combinators:

1. Every function has a fixed point.

2. A fixed-point combinator will compute it.

So what is the fixed point of f(x) = x + 1?

Also why doesn't this give us mathematical superpowers? Define f(x) = x iff x is a non-trivial zero of the Riemann zeta function...

[+] gregfjohnson|2 years ago|reply
Here is a way to look at this in concrete terms, using python.

An important class of lambda terms are those for which there is no normal form. In computational terms, these are terms that would cause you to go into an infinite loop if you tried to apply the conversion rules of lambda calculus "until" you reached a normal form (i.e., a lambda term for which there are no beta redexes).

Canonical example:

  >>> (lambda fn: fn(fn)) (lambda fn: fn(fn))
  Traceback (most recent call last):
  ...
  RecursionError: maximum recursion depth exceeded
For many functions, the fixed point turns out to be a variant of this divergent ("infinite loop") expression. Assuming a definition of "+" that preserves divergence, then "infinite_loop" is a fixed point of f(n) = n + 1.

An encoding of the fixed point operator in python is:

  y = lambda Input_Fn:((lambda f: lambda n: Input_Fn(f(f))(n)) \
                       (lambda f: lambda n: Input_Fn(f(f))(n)))
For fun, we will play a little bit fast and loose, and combine standard integer arithmetic with lambda calculus.

Here is a functional whose fixed point is the factorial function:

  >>> fac1 = lambda f: lambda n: ((n > 1) and n * f(n-1) or 1)
Example evaluation:

  >>> y(fac1)(4)
  24
If we use the standard encoding of the integers as Church numerals, two would be represented as:

  two = lambda successor: lambda zero: successor(successor(zero))
The "add_one" function becomes:

  add_one = lambda n: lambda successor: lambda zero: successor(n(successor)(zero))
For concreteness (and human intuition), we can define

  int_zero, int_successor = 0, (lambda n: n+1)
  >>> add_one(two)(int_successor)(int_zero)
  3
What is a fixed point of the add_one function?

  >>> y(add_one)(two)(int_successor)(int_zero)
  Traceback (most recent call last):
  ...
  RecursionError: maximum recursion depth exceeded
[+] mrkeen|2 years ago|reply
I don't understand the formal side of things, but I've used Y before, so here goes:

In the lambda calculus, functions are nameless. Recursion is when an expression refers to itself by name. The Y combinator gives you recursion despite the contradiction in my last two sentences.

> So what is the fixed point of f(x) = x + 1?

We don't have names, so what is the fixed point of (λx. x + 1)? Introduce a new variable into the expression's body to act as the expression's name, and also include it as the first parameter:

  (λf x. x + 1)
(Your function did not refer to itself which is why there's no f in the body of the above expression).

Now let's take the ingredients and put them together. I'm including an 'input' so that we can converge on an output:

  Y     = (λg. (λh. g (h h)) (λh. g (h h)))
  fixf  = (λf x. x + 1)
  input = 3

  Y fixf input = (λg. (λh. g (h h)) (λh. g (h h))) (λf x. x + 1) 3
Now we just apply those lambdas to their terms and see what we end up with:

  (λg. (λh. g (h h)) (λh. g (h h))) (λf x. x + 1) 3
    ^                               |     g     |

  (λh. (λf x. x + 1) (h h)) (λh. (λf x. x + 1) (h h)) 3
    ^                       |        h       |

  (λf x. x + 1) ((λh. (λf x. x + 1) (h h)) (λh. (λf x. x + 1) (h h))) 3
    ^           |                        f                          |

  (λx. x + 1) 3
    ^        |x|

  4
[+] cryptonector|2 years ago|reply
It's a tool for constructing recursive functions when the language does not support a function calling itself by name. That happens if, for example, the language won't finish compiling the function and making a symbol with its name available for binding/linking until it's done compiling it, so.. in such a case you can't recurse by name. So what to do? Well, you make your recursive function take an extra parameter that is also a function value, and then you'll define a function that calls your wannabe-recursive function with.. itself as the argument function so that it can then call itself as intended.

It's quite simple when thought of that way. "Fixed point" can seem like a high falutin' term of art, and that's because it is -- we love our terms of art, but we also need to be able to explain them.

`fix` then is a function which takes a function value as an argument and which returns a new function value which is a function that calls the argument to `fix` with that same argument as its first argument. Reading that I realize it's hard to express this in pure natural language -- one has to introduce symbols for naming the various functions.

[+] LudwigNagasena|2 years ago|reply
Every function in untyped lambda calculus has a fixed point. The fixed point of f(x) = x + 1 is garbage that cannot be decoded back into a number.
[+] QuesnayJr|2 years ago|reply
If it doesn't really have a fixed point you get a function that never terminates. In denotational semantics you define a special value, "bottom" that means "undefined", and the fixed point is bottom.

And it's not all functions, just computable ones. But if there's algorithm to compute non-trivial zeroes of the zeta function, it would just never terminate if there aren't any.

[+] tromp|2 years ago|reply
The fixed point of any function f = f (f (f (f ....

so for f(x)=1+x it is 1+ (1+ (1+ (1+ ... , an infinite sum.

This is correct in the sense that 1 + infinity = infinity, but in practice this could result in an infinite loop or stack overflow.

For f(x)=x+1 it's the reverse ...) +1) +1) +1 which behaves similarly.

[+] defrost|2 years ago|reply
1. No. - https://en.wikipedia.org/wiki/Fixed-point_combinator

In a generic context a fixed point combinator will only return a fixed point of a function if one exists.

2. No. (see: 1. above)

Your confusion stems from the usual domain of application to function spaces where every function has a fixed point (ie. not all function spaces, just those that are made up of functions with at least one fixed point).

From the link above:

    In the classical untyped lambda calculus, every function has a fixed point.
[+] bendsawyer|2 years ago|reply
I had not realized that's where Y Combinator comes from... Recursion without self reference. Cool.
[+] stevefan1999|2 years ago|reply
I had a feeling that Y combinator just sounds like recursion but with lazy evaluation...please correct me if I'm wrong.
[+] mrkeen|2 years ago|reply
I don't think the laziness is as important as the namelessness.

It's for when you want to recurse (a function calling its own name) in an environment where you don't have names (the lambda calculus).

[+] konstantinua00|2 years ago|reply
I don't get it

example shows that it's y(g)->g(y(g)), not the opposite...

[+] youzicha|2 years ago|reply
Indeed. I think this something that people are often confused about, e.g. one blogger[0] comments:

> The key to understanding the fixpoint theorem, for me anyway, was realizing that when it says FG=G, it does not mean that for every F there is a G such that by calling F with parameter G one can get back G. I mention this in the blog post, above. The equality operator in FG=G is the equivalence relation induced by the calculus rewriting relation: that is, it's the symmetric reflexive transitive closure of the rewriting step relation. When you look at the proof of the theorem, it actually works by constructing an expression G such that evaluating G produces, as an intermediate result, FG. There is no need for F to even be a function, and if F is a function it doesn't matter what, if anything, F would actually do when called, because the proof of the theorem doesn't involve calling F.

I think the name "fixpoint combinator" is kindof bad, it it was called e.g. the "recursion combinator" I think people would find it more intuitive.

[0] https://fexpr.blogspot.com/2013/07/bypassing-no-go-theorems....

[+] toxik|2 years ago|reply
No, it shows that `Y g = g (Y g)`, so both ways.
[+] svat|2 years ago|reply
What do you mean by "the opposite"? In your notation, the example shows that

    Y(g) = g(Y(g))
which by the definition of the equals sign (A=B and B=A say the same thing), is the same as:

    g(Y(g)) = Y(g)
— so Y(g) is a fixed point of g. What is the confusion?