Memoization in OCaml? - recursion

It is possible to improve "raw" Fibonacci recursive procedure
Fib[n_] := If[n < 2, n, Fib[n - 1] + Fib[n - 2]]
with
Fib[n_] := Fib[n] = If[n < 2, n, Fib[n - 1] + Fib[n - 2]]
in Wolfram Mathematica.
First version will suffer from exponential explosion while second one will not since Mathematica will see repeating function calls in expression and memoize (reuse) them.
Is it possible to do the same in OCaml?
How to improve
let rec fib n = if n<2 then n else fib (n-1) + fib (n-2);;
in the same manner?

The solution provided by rgrinberg can be generalized so that we can memoize any function. I am going to use associative lists instead of hashtables. But it does not really matter, you can easily convert all my examples to use hashtables.
First, here is a function memo which takes another function and returns its memoized version. It is what nlucaroni suggested in one of the comments:
let memo f =
let m = ref [] in
fun x ->
try
List.assoc x !m
with
Not_found ->
let y = f x in
m := (x, y) :: !m ;
y
The function memo f keeps a list m of results computed so far. When asked to compute f x it first checks m to see if f x has been computed already. If yes, it returns the result, otherwise it actually computes f x, stores the result in m, and returns it.
There is a problem with the above memo in case f is recursive. Once memo calls f to compute f x, any recursive calls made by f will not be intercepted by memo. To solve this problem we need to do two things:
In the definition of such a recursive f we need to substitute recursive calls with calls to a function "to be provided later" (this will be the memoized version of f).
In memo f we need to provide f with the promised "function which you should call when you want to make a recursive call".
This leads to the following solution:
let memo_rec f =
let m = ref [] in
let rec g x =
try
List.assoc x !m
with
Not_found ->
let y = f g x in
m := (x, y) :: !m ;
y
in
g
To demonstrate how this works, let us memoize the naive Fibonacci function. We need to write it so that it accepts an extra argument, which I will call self. This argument is what the function should use instead of recursively calling itself:
let fib self = function
0 -> 1
| 1 -> 1
| n -> self (n - 1) + self (n - 2)
Now to get the memoized fib, we compute
let fib_memoized = memo_rec fib
You are welcome to try it out to see that fib_memoized 50 returns instantly. (This is not so for memo f where f is the usual naive recursive definition.)

You pretty much do what the mathematica version does but manually:
let rec fib =
let cache = Hashtbl.create 10 in
begin fun n ->
try Hashtbl.find cache n
with Not_found -> begin
if n < 2 then n
else
let f = fib (n-1) + fib (n-2) in
Hashtbl.add cache n f; f
end
end
Here I choose a hashtable to store already computed results instead of recomputing them.
Note that you should still beware of integer overflow since we are using a normal and not a big int.

Related

Is there an equivalent for map or fmap to replace while loops?

Haskell replaces for loops over iteratable objects with map :: (a -> b) -> [a] -> [b] or
fmap :: (a -> b) -> f a -> f b. (This question isn't limited to Haskell, I'm just using the syntax here.)
Is there something similar that replaces a while loop, like
wmap :: ([a] -> b) -> [a] -> ([b] -> Bool) -> [b]?
This function returns a list of b.
The first argument is a function that takes a list and computes a value that will end up in the list returned by wmap (so it's a very specific kind of while loop).
The second argument is the list that we use as our starting point.
The third argument is a function that evaluates the stoping criteria.
And as a functor,
wfmap :: (f a -> b) -> f a -> (f b -> Bool) -> f b
For example, a Jacobi solver would look like this (with b now the same type as a):
jacobi :: ([a] -> [a]) -> [a] -> ([a] -> Bool) -> [a]
What I'm looking for isn't really pure. wmap could have values that mutate internally, but only exist inside the function. It also has nondeterministic runtime, if it terminates at all.
In the case of a Gauss-Seidel solver, there would be no return value, since the [a] would be modified in place.
Something like this:
gs :: ([a] -> [a]) -> [a] -> ([a] -> Bool) -> ???
Does wmap or wfmap exist as part of any language by default, and what is it called?
Answer 1 (thanks to Bergi): Instead of the silly wmap/wfmap signature, we already have until.
Does an in place version of until exist for things like gs?
There is a proverb in engineering which states "Don't generalize before you have at least 3 implementations". There is some truth to it - especially when looking for new functional iteration concepts before doing it by foot a few times.
"Doing it by foot" here means, you should - if there is no friendly helper function you know of - resort to recursion. Write your "special cases" recursively. Preferably in a tail recursive form. Then, if you start to see recurring patterns, you might come up with a way to refactor into some recurring iteration scheme and its "kernel".
Let's for the sake of clarification of the above, assume you never heard of foldl and you want accumulate a result from iteration over a list... Then, you would write something like:
myAvg values =
total / (length values)
where
mySum acc [] = acc
mySum acc (x:xs) = mySum (acc + x) xs
total = mySum 0 values
And after doing this a couple of times, the pattern might show, that the recursions in those where clauses always look darn similar. You might then come up with a name like "fold" or "reduce" for that inner recursion snippet and end up with:
myAvg values = (foldl (+) 0.0 values) / fromIntegral (length values) :: Float
So, if you are looking for helper functions which help with your use-cases, my advice is you first write a few instances as recursive functions and then look for patterns.
So, with all that said, let's get our fingers wet and see how the Jacobi algorithm could translate to Haskell. Just so we have something to talk about. Now - usually I do not use Haskell for anything requiring arrays (containers with O(1) element access), because there are at least 5 array packages I know of and I would have to read for 2 days to decide which one is suitable for my application. TL;DR;). So I stick with lists and NO package dependencies beyond prelude in the code below. But that is - given the size of the example equations we try to solve is tiny - not a bad thing at all. Plus, the code demonstrates, that list comprehensions in lazy Haskell allow for un-imperative and yet performant operations on sets of cells (e.g. in the matrix), without any need for explicit looping.
type Matrix = [[Double]]
-- sorry - my mind went blank while looking for a better name for this...
-- but it is useful nonetheless
idefix nr nc =
[ [(r,c) | c <- [0..nc-1]] | r <- [0..nr-1]]
matElem m (r,c) = (m !! r) !! c
transpose (r,c) = (c,r)
matrixDim m = (length m, length . head $ m)
-- constructs a Matrix by enumerating the indices and querying
-- 'unfolder' for a value.
-- try "unfoldMatrix 3 3 id" and you see how indices relate to
-- cells in the matrix.
unfoldMatrix nr nc unfolder =
fmap (\row -> fmap (\cell -> unfolder cell) row) $ idefix nr nc
-- Not really needed for Jacobi problem but good
-- training to get our fingers wet with unfoldMatrix.
transposeMatrix m =
let (nr,nc) = matrixDim m in
unfoldMatrix nc nr (matElem m . transpose)
addMatrix m1 m2
| (matrixDim m1) == (matrixDim m2) =
let (nr,nc) = matrixDim m1 in
unfoldMatrix nr nc (\idx -> matElem m1 idx + matElem m2 idx)
subMatrix m1 m2
| (matrixDim m1) == (matrixDim m2) =
let (nr,nc) = matrixDim m1 in
unfoldMatrix nr nc (\idx -> matElem m1 idx - matElem m2 idx)
dluMatrix :: Matrix -> (Matrix,Matrix,Matrix)
dluMatrix m
| (fst . matrixDim $ m) == (snd . matrixDim $ m) =
let n = fst . matrixDim $ m in
(unfoldMatrix n n (\(r,c) -> if r == c then matElem m (r,c) else 0.0)
,unfoldMatrix n n (\(r,c) -> if r > c then matElem m (r,c) else 0.0)
,unfoldMatrix n n (\(r,c) -> if c > r then matElem m (r,c) else 0.0)
)
mulMatrix m1 m2
| (snd . matrixDim $ m1) == (fst . matrixDim $ m2) =
let (nr, nc) = ((fst . matrixDim $ m1),(snd . matrixDim $ m2)) in
unfoldMatrix nr nc
(\(ro,co) ->
sum [ matElem m1 (ro,i) * matElem m2 (i,co) | i <- [0..nr-1]]
)
isSquareMatrix m = let (nr,nc) = matrixDim m in nr == nc
jacobi :: Double -> Matrix -> Matrix -> Matrix -> Matrix
jacobi errMax a b x0
| isSquareMatrix a && (snd . matrixDim $ a) == (fst . matrixDim $ b) =
approximate x0
-- We could possibly avoid our hand rolled recursion
-- with the help of 'loop' from Control.Monad.Extra
-- according to hoogle. But it would not look better at all.
-- loop (\x -> let x' = jacobiStep x in if converged x' then Right x' else Left x') x0
where
(nra, nca) = matrixDim a
(d,l,u) = dluMatrix a
dinv = unfoldMatrix nra nca (\(r,c) ->
if r == c
then 1.0 / matElem d (r,c)
else 0.0)
lu = addMatrix l u
converged x =
let delta = (subMatrix (mulMatrix a x) b) in
let (nrd,ncd) = matrixDim delta in
let err = sum (fmap (\idx -> let v = matElem delta idx in v * v)
(concat (idefix nrd ncd))) in
err < errMax
jacobiStep x =
(mulMatrix dinv (subMatrix b (mulMatrix lu x)))
approximate x =
let x' = jacobiStep x in
if converged x' then x' else approximate x'
wikiExample errMax =
let a = [[ 2.0, 1.0],[5.0,7.0]] in
let b = [[11], [13]] in
jacobi errMax a b [[1.0],[1.0]]
Function idefix, despite it's silly name, IMHO is an eye opener for people coming from non-lazy languages. Their first reflex is to get scared: "What - he creates a list with the indices instead of writing loops? What a waste!" But a waste, it is not in lazy languages. What you see in this function (the list comprehension) produces a lazy list. It is not really created. What happens behind the scene is similar in spirit to what LINQ does in C# - IEnumerator<T> juggling.
We use idefix a second time when we want to sum all elements in our delta. There, we do not care about the concrete structure of the matrix. And so we use the standard prelude function concat to flatten the Matrix into a linear list. Lazy as well, of course. That is the beauty.
The next notable difference to the imperative wikipedia pseudo code is, that using matrix notation is much less complicated compared to nested looping and operating on single cells. Fortunately, the wikipedia article shows both. So, instead of a while loop with 2 nested loops, we only need an equivalent of the outermost while loop. Which is covered by our 2 liner recursive function approximate.
Lessons learned:
Lists and list comprehensions can help simplify code otherwise requiring nested loops. (In lazy languages).
Ocaml and Common Lisp have mutability and built in arrays and loops. That makes a package, very convenient when translating algorithms from imperative languages or imperative pseudo code.
Haskell has immutability and no built in arrays and no loops, but instead it has a similarly powerful set of tools, namely Laziness, tail call optimization and a terse syntax. That combination requires more planning (and writing some usually short helper functions) instead of the classical C approach of "Let's write it all in main()."
Sometimes it is easier to write a 2 line long recursive function than to think about how to abstract it.
In FP, you don't usually try to fit everything "inside the loop." You do one step and pass it on to the next function. There are lots of combinations that are useful in different situations. A common replacement for a while loop is a map followed by a takeWhile or a dropWhile, but there are many other possibilities, up to just plain recursion.

For Loop Over a Recursive Call Ocaml

I'm working on an implementation of prime decomposition in OCaml. I am not a functional programmer; Below is my code. The prime decomposition happens recursively in the prime_part function. primes is the list of primes from 0 to num. The goal here being that I could type prime_part into the OCaml interpreter and have it spit out when n = 20, k = 1.
2 + 3 + 7
5 + 7
I adapted is_prime and all_primes from an OCaml tutorial. all_primes will need to be called to generate a list of primes up to b prior to prime_part being called.
(* adapted from http://www.ocaml.org/learn/tutorials/99problems.html *)
let is_prime n =
let n = abs n in
let rec is_not_divisor d =
d * d > n || (n mod d <> 0 && is_not_divisor (d+1)) in
n <> 1 && is_not_divisor 2;;
let rec all_primes a b =
if a > b then [] else
let rest = all_primes (a + 1) b in
if is_prime a then a :: rest else rest;;
let f elem =
Printf.printf "%d + " elem
let rec prime_part n k lst primes =
let h elem =
if elem > k then
append_item lst elem;
prime_part (n-elem) elem lst primes in
if n == 0 then begin
List.iter f lst;
Printf.printf "\n";
()
end
else
if n <= k then
()
else
List.iter h primes;
();;
let main num =
prime_part num 1 [] (all_primes 2 num)
I'm largely confused with the reclusive nature with the for loop. I see that List.ittr is the OCaml way, but I lose access to my variables if I define another function for List.ittr. I need access to those variables to recursively call prime_part. What is a better way of doing this?
I can articulate in Ruby what I'm trying to accomplish with OCaml. n = any number, k = 1, lst = [], primes = a list of prime number 0 to n
def prime_part_constructive(n, k, lst, primes)
if n == 0
print(lst.join(' + '))
puts()
end
if n <= k
return
end
primes.each{ |i|
next if i <= k
prime_part_constructive(n - i, i, lst+[i], primes)
}
end
Here are a few comments on your code.
You can define nested functions in OCaml. Nested functions have access to all previously defined names. So you can use List.iter without losing access to your local variables.
I don't see any reason that your function prime_part_constructive returns an integer value. It would be more idiomatic in OCaml for it to return the value (), known as "unit". This is the value returned by functions that are called for their side effects (such as printing values).
The notation a.(i) is for accessing arrays, not lists. Lists and arrays are not the same in OCaml. If you replace your for with List.iter you won't have to worry about this.
To concatenate two lists, use the # operator. The notation lst.concat doesn't make sense in OCaml.
Update
Here's how it looks to have a nested function. This made up function takes a number n and a list of ints, then writes out the value of each element of the list multiplied by n.
let write_mults n lst =
let write1 m = Printf.printf " %d" (m * n) in
List.iter write1 lst
The write1 function is a nested function. Note that it has access to the value of n.
Update 2
Here's what I got when I wrote up the function:
let prime_part n primes =
let rec go residue k lst accum =
if residue < 0 then
accum
else if residue = 0 then
lst :: accum
else
let f a p =
if p <= k then a
else go (residue - p) p (p :: lst) a
in
List.fold_left f accum primes
in
go n 1 [] []
It works for your example:
val prime_part : int -> int list -> int list list = <fun>
# prime_part 12 [2;3;5;7;11];;
- : int list list = [[7; 5]; [7; 3; 2]]
Note that this function returns the list of partitions. This is much more useful (and functional) than writing them out (IMHO).

A better way to understand the logic of nested functions (Currying)

I am learning Jason Hickey's Introduction to Objective Caml. Just have a question about nested functions (currying).
there is a existing question How to understand the "Currying" in Haskell?, but I guess I am seeking for the answer of slightly different question.
It says that we can write let sum = fun i j -> i + j;; as let sum = fun i -> fun j -> i + j;;
My question is simple:
Can I understand the above definition in this way: let sum = fun i -> i + fun j -> j;;?
I know it won't pass the compiler, but I just try to map this kind of OCaml function definition to the mathematics functions.
In my above imagination, we can write the function easily in mathematics, f(i) = i + g(j); and g(j) = j.
Should I always do this kind of logic mapping for easy understanding?
Your imagination is not really correct: f(i) = i + g(j) doesn't mean much as j is undefined here.
A correct way to understand fun i j -> foo is to consider it some convenient syntactic sugar for the more explicit notation fun i -> fun j -> foo.
All the definitions below are exactly equivalent :
let sum i j = i + j
let sum i = fun j -> i + j
let sum = fun i -> (fun j -> i + j)
let sum = fun i -> fun j -> i + j
let sum = fun i j -> i + j
let sum i =
let add_i = fun j -> i + j in
add_i
Mathematically this could be written (i ↦ (j ↦ i+j)), as an element of
the function space (ℕ → (ℕ → ℕ)).
OCaml functions can be directly mapped to and from mathematical notation. However, you need to realize that mathematical notation is ambiguous. There is not a clear distinction between the value of the function, f(i), on a particular value i, and the function f itself. Often one writes f(i) when one means the function f itself. ("Let us consider a function f(i)=i+1... This function is ...") To write correct code in OCaml, you have to see clearly whether you are working with a function itself or with the value of a function.
When you say in mathematical notation, "Consider the function f(i,j)=i+g(j) where g(j)=j, you are writing the values of the functions. In OCaml, this is translated to
let f i j =
let g j = j in
i + g j;;
or
let f =
let g = fun j -> j
in
fun i j -> i + g j;;
If you are trying to write let sum = fun i -> i + fun j -> j;;, then in mathematical notation you are saying "Consider the function sum such that sum(i) = i + g, where g is a function defined by g(j)=j." This is mathematically incorrect: you cannot add an integer value i and a function g. You can only add an integer i and the value of the function g on some other integer j. The expression "i+g" is undefined, strictly speaking. Either you wanted to write i + g(i), or i+g(j), but not i+g. This is so in mathematics, and this is so in OCaml.

Stack overflow during evaluation (looping recursion?). OCaml

I'm trying to write a function that accepts an int n and returns a list that runs down from n to 0.
This is what I have
let rec downFrom n =
let m = n+1 in
if m = 0 then
[]
else
(m-1) :: downFrom (m - 1);;
The function compiles ok but when I test it with any int it gives me the error
Stack overflow during evaluation (looping recursion?).
I know it's the local varible that gets in the way but I don't know another way to declare it. Thank you!!!
First, the real thing wrong with your program is that you have an infinite loop. Why, because your inductive base case is 0, but you always stay at n! This is because you recurse on m - 1 which is really n + 1 - 1
I'm surprised as to why this compiles, because it doesn't include the rec keyword, which is necessary on recursive functions. To avoid stack overflows in OCaml, you generally switch to a tail recursive style, such as follows:
let downFrom n =
let rec h n acc =
if n = 0 then List.rev acc else h (n-1) (n::acc)
in
h n []
Someone suggested the following edit:
let downFrom n =
let rec h m acc =
if m > n then acc else h (m + 1) (m::acc)
in
h 0 [];
This saves a call to List.rev, I agree.
The key with recursion is that the recursive call has to be a smaller version of the problem. Your recursive call doesn't create a smaller version of the problem. It just repeats the same problem.
You can try with a filtering parameter
syntax:
let f = function
p1 -> expr1
| p2 -> expr2
| p3 -> ...;;
let rec n_to_one =function
0->[]
|n->n::n_to_one (n-1);;
# n_to_one 3;;
- : int list = [3; 2; 1]

What is a Y-combinator? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
A Y-combinator is a computer science concept from the “functional” side of things. Most programmers don't know much at all about combinators, if they've even heard about them.
What is a Y-combinator?
How do combinators work?
What are they good for?
Are they useful in procedural languages?
A Y-combinator is a "functional" (a function that operates on other functions) that enables recursion, when you can't refer to the function from within itself. In computer-science theory, it generalizes recursion, abstracting its implementation, and thereby separating it from the actual work of the function in question. The benefit of not needing a compile-time name for the recursive function is sort of a bonus. =)
This is applicable in languages that support lambda functions. The expression-based nature of lambdas usually means that they cannot refer to themselves by name. And working around this by way of declaring the variable, refering to it, then assigning the lambda to it, to complete the self-reference loop, is brittle. The lambda variable can be copied, and the original variable re-assigned, which breaks the self-reference.
Y-combinators are cumbersome to implement, and often to use, in static-typed languages (which procedural languages often are), because usually typing restrictions require the number of arguments for the function in question to be known at compile time. This means that a y-combinator must be written for any argument count that one needs to use.
Below is an example of how the usage and working of a Y-Combinator, in C#.
Using a Y-combinator involves an "unusual" way of constructing a recursive function. First you must write your function as a piece of code that calls a pre-existing function, rather than itself:
// Factorial, if func does the same thing as this bit of code...
x == 0 ? 1: x * func(x - 1);
Then you turn that into a function that takes a function to call, and returns a function that does so. This is called a functional, because it takes one function, and performs an operation with it that results in another function.
// A function that creates a factorial, but only if you pass in
// a function that does what the inner function is doing.
Func<Func<Double, Double>, Func<Double, Double>> fact =
(recurs) =>
(x) =>
x == 0 ? 1 : x * recurs(x - 1);
Now you have a function that takes a function, and returns another function that sort of looks like a factorial, but instead of calling itself, it calls the argument passed into the outer function. How do you make this the factorial? Pass the inner function to itself. The Y-Combinator does that, by being a function with a permanent name, which can introduce the recursion.
// One-argument Y-Combinator.
public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F)
{
return
t => // A function that...
F( // Calls the factorial creator, passing in...
Y(F) // The result of this same Y-combinator function call...
// (Here is where the recursion is introduced.)
)
(t); // And passes the argument into the work function.
}
Rather than the factorial calling itself, what happens is that the factorial calls the factorial generator (returned by the recursive call to Y-Combinator). And depending on the current value of t the function returned from the generator will either call the generator again, with t - 1, or just return 1, terminating the recursion.
It's complicated and cryptic, but it all shakes out at run-time, and the key to its working is "deferred execution", and the breaking up of the recursion to span two functions. The inner F is passed as an argument, to be called in the next iteration, only if necessary.
If you're ready for a long read, Mike Vanier has a great explanation. Long story short, it allows you to implement recursion in a language that doesn't necessarily support it natively.
I've lifted this from http://www.mail-archive.com/boston-pm#mail.pm.org/msg02716.html which is an explanation I wrote several years ago.
I'll use JavaScript in this example, but many other languages will work as well.
Our goal is to be able to write a recursive function of 1
variable using only functions of 1 variables and no
assignments, defining things by name, etc. (Why this is our
goal is another question, let's just take this as the
challenge that we're given.) Seems impossible, huh? As
an example, let's implement factorial.
Well step 1 is to say that we could do this easily if we
cheated a little. Using functions of 2 variables and
assignment we can at least avoid having to use
assignment to set up the recursion.
// Here's the function that we want to recurse.
X = function (recurse, n) {
if (0 == n)
return 1;
else
return n * recurse(recurse, n - 1);
};
// This will get X to recurse.
Y = function (builder, n) {
return builder(builder, n);
};
// Here it is in action.
Y(
X,
5
);
Now let's see if we can cheat less. Well firstly we're using
assignment, but we don't need to. We can just write X and
Y inline.
// No assignment this time.
function (builder, n) {
return builder(builder, n);
}(
function (recurse, n) {
if (0 == n)
return 1;
else
return n * recurse(recurse, n - 1);
},
5
);
But we're using functions of 2 variables to get a function of 1
variable. Can we fix that? Well a smart guy by the name of
Haskell Curry has a neat trick, if you have good higher order
functions then you only need functions of 1 variable. The
proof is that you can get from functions of 2 (or more in the
general case) variables to 1 variable with a purely
mechanical text transformation like this:
// Original
F = function (i, j) {
...
};
F(i,j);
// Transformed
F = function (i) { return function (j) {
...
}};
F(i)(j);
where ... remains exactly the same. (This trick is called
"currying" after its inventor. The language Haskell is also
named for Haskell Curry. File that under useless trivia.)
Now just apply this transformation everywhere and we get
our final version.
// The dreaded Y-combinator in action!
function (builder) { return function (n) {
return builder(builder)(n);
}}(
function (recurse) { return function (n) {
if (0 == n)
return 1;
else
return n * recurse(recurse)(n - 1);
}})(
5
);
Feel free to try it. alert() that return, tie it to a button, whatever.
That code calculates factorials, recursively, without using
assignment, declarations, or functions of 2 variables. (But
trying to trace how it works is likely to make your head spin.
And handing it, without the derivation, just slightly reformatted
will result in code that is sure to baffle and confuse.)
You can replace the 4 lines that recursively define factorial with
any other recursive function that you want.
I wonder if there's any use in attempting to build this from the ground up. Let's see. Here's a basic, recursive factorial function:
function factorial(n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
Let's refactor and create a new function called fact that returns an anonymous factorial-computing function instead of performing the calculation itself:
function fact() {
return function(n) {
return n == 0 ? 1 : n * fact()(n - 1);
};
}
var factorial = fact();
That's a little weird, but there's nothing wrong with it. We're just generating a new factorial function at each step.
The recursion at this stage is still fairly explicit. The fact function needs to be aware of its own name. Let's parameterize the recursive call:
function fact(recurse) {
return function(n) {
return n == 0 ? 1 : n * recurse(n - 1);
};
}
function recurser(x) {
return fact(recurser)(x);
}
var factorial = fact(recurser);
That's great, but recurser still needs to know its own name. Let's parameterize that, too:
function recurser(f) {
return fact(function(x) {
return f(f)(x);
});
}
var factorial = recurser(recurser);
Now, instead of calling recurser(recurser) directly, let's create a wrapper function that returns its result:
function Y() {
return (function(f) {
return f(f);
})(recurser);
}
var factorial = Y();
We can now get rid of the recurser name altogether; it's just an argument to Y's inner function, which can be replaced with the function itself:
function Y() {
return (function(f) {
return f(f);
})(function(f) {
return fact(function(x) {
return f(f)(x);
});
});
}
var factorial = Y();
The only external name still referenced is fact, but it should be clear by now that that's easily parameterized, too, creating the complete, generic, solution:
function Y(le) {
return (function(f) {
return f(f);
})(function(f) {
return le(function(x) {
return f(f)(x);
});
});
}
var factorial = Y(function(recurse) {
return function(n) {
return n == 0 ? 1 : n * recurse(n - 1);
};
});
Most of the answers above describe what the Y-combinator is but not what it is for.
Fixed point combinators are used to show that lambda calculus is turing complete. This is a very important result in the theory of computation and provides a theoretical foundation for functional programming.
Studying fixed point combinators has also helped me really understand functional programming. I have never found any use for them in actual programming though.
For programmers who haven't encountered functional programming in depth, and don't care to start now, but are mildly curious:
The Y combinator is a formula which lets you implement recursion in a situation where functions can't have names but can be passed around as arguments, used as return values, and defined within other functions.
It works by passing the function to itself as an argument, so it can call itself.
It's part of the lambda calculus, which is really maths but is effectively a programming language, and is pretty fundamental to computer science and especially to functional programming.
The day to day practical value of the Y combinator is limited, since programming languages tend to let you name functions.
In case you need to identify it in a police lineup, it looks like this:
Y = λf.(λx.f (x x)) (λx.f (x x))
You can usually spot it because of the repeated (λx.f (x x)).
The λ symbols are the Greek letter lambda, which gives the lambda calculus its name, and there's a lot of (λx.t) style terms because that's what the lambda calculus looks like.
y-combinator in JavaScript:
var Y = function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f(h(h)).apply(null, arguments);
};
});
};
var factorial = Y(function(recurse) {
return function(x) {
return x == 0 ? 1 : x * recurse(x-1);
};
});
factorial(5) // -> 120
Edit:
I learn a lot from looking at code, but this one is a bit tough to swallow without some background - sorry about that. With some general knowledge presented by other answers, you can begin to pick apart what is happening.
The Y function is the "y-combinator". Now take a look at the var factorial line where Y is used. Notice you pass a function to it that has a parameter (in this example, recurse) that is also used later on in the inner function. The parameter name basically becomes the name of the inner function allowing it to perform a recursive call (since it uses recurse() in it's definition.) The y-combinator performs the magic of associating the otherwise anonymous inner function with the parameter name of the function passed to Y.
For the full explanation of how Y does the magic, checked out the linked article (not by me btw.)
Anonymous recursion
A fixed-point combinator is a higher-order function fix that by definition satisfies the equivalence
forall f. fix f = f (fix f)
fix f represents a solution x to the fixed-point equation
x = f x
The factorial of a natural number can be proved by
fact 0 = 1
fact n = n * fact (n - 1)
Using fix, arbitrary constructive proofs over general/μ-recursive functions can be derived without nonymous self-referentiality.
fact n = (fix fact') n
where
fact' rec n = if n == 0
then 1
else n * rec (n - 1)
such that
fact 3
= (fix fact') 3
= fact' (fix fact') 3
= if 3 == 0 then 1 else 3 * (fix fact') (3 - 1)
= 3 * (fix fact') 2
= 3 * fact' (fix fact') 2
= 3 * if 2 == 0 then 1 else 2 * (fix fact') (2 - 1)
= 3 * 2 * (fix fact') 1
= 3 * 2 * fact' (fix fact') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (fix fact') (1 - 1)
= 3 * 2 * 1 * (fix fact') 0
= 3 * 2 * 1 * fact' (fix fact') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (fix fact') (0 - 1)
= 3 * 2 * 1 * 1
= 6
This formal proof that
fact 3 = 6
methodically uses the fixed-point combinator equivalence for rewrites
fix fact' -> fact' (fix fact')
Lambda calculus
The untyped lambda calculus formalism consists in a context-free grammar
E ::= v Variable
| λ v. E Abstraction
|  E E Application
where v ranges over variables, together with the beta and eta reduction rules
(λ x. B) E -> B[x := E] Beta
λ x. E x -> E if x doesn’t occur free in E Eta
Beta reduction substitutes all free occurrences of the variable x in the abstraction (“function”) body B by the expression (“argument”) E. Eta reduction eliminates redundant abstraction. It is sometimes omitted from the formalism. An irreducible expression, to which no reduction rule applies, is in normal or canonical form.
λ x y. E
is shorthand for
λ x. λ y. E
(abstraction multiarity),
E F G
is shorthand for
(E F) G
(application left-associativity),
λ x. x
and
λ y. y
are alpha-equivalent.
Abstraction and application are the two only “language primitives” of the lambda calculus, but they allow encoding of arbitrarily complex data and operations.
The Church numerals are an encoding of the natural numbers similar to the Peano-axiomatic naturals.
0 = λ f x. x No application
1 = λ f x. f x One application
2 = λ f x. f (f x) Twofold
3 = λ f x. f (f (f x)) Threefold
. . .
SUCC = λ n f x. f (n f x) Successor
ADD = λ n m f x. n f (m f x) Addition
MULT = λ n m f x. n (m f) x Multiplication
. . .
A formal proof that
1 + 2 = 3
using the rewrite rule of beta reduction:
ADD 1 2
= (λ n m f x. n f (m f x)) (λ g y. g y) (λ h z. h (h z))
= (λ m f x. (λ g y. g y) f (m f x)) (λ h z. h (h z))
= (λ m f x. (λ y. f y) (m f x)) (λ h z. h (h z))
= (λ m f x. f (m f x)) (λ h z. h (h z))
= λ f x. f ((λ h z. h (h z)) f x)
= λ f x. f ((λ z. f (f z)) x)
= λ f x. f (f (f x)) Normal form
= 3
Combinators
In lambda calculus, combinators are abstractions that contain no free variables. Most simply: I, the identity combinator
λ x. x
isomorphic to the identity function
id x = x
Such combinators are the primitive operators of combinator calculi like the SKI system.
S = λ x y z. x z (y z)
K = λ x y. x
I = λ x. x
Beta reduction is not strongly normalizing; not all reducible expressions, “redexes”, converge to normal form under beta reduction. A simple example is divergent application of the omega ω combinator
λ x. x x
to itself:
(λ x. x x) (λ y. y y)
= (λ y. y y) (λ y. y y)
. . .
= _|_ Bottom
Reduction of leftmost subexpressions (“heads”) is prioritized. Applicative order normalizes arguments before substitution, normal order does not. The two strategies are analogous to eager evaluation, e.g. C, and lazy evaluation, e.g. Haskell.
K (I a) (ω ω)
= (λ k l. k) ((λ i. i) a) ((λ x. x x) (λ y. y y))
diverges under eager applicative-order beta reduction
= (λ k l. k) a ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ y. y y) (λ y. y y))
. . .
= _|_
since in strict semantics
forall f. f _|_ = _|_
but converges under lazy normal-order beta reduction
= (λ l. ((λ i. i) a)) ((λ x. x x) (λ y. y y))
= (λ l. a) ((λ x. x x) (λ y. y y))
= a
If an expression has a normal form, normal-order beta reduction will find it.
Y
The essential property of the Y fixed-point combinator
λ f. (λ x. f (x x)) (λ x. f (x x))
is given by
Y g
= (λ f. (λ x. f (x x)) (λ x. f (x x))) g
= (λ x. g (x x)) (λ x. g (x x)) = Y g
= g ((λ x. g (x x)) (λ x. g (x x))) = g (Y g)
= g (g ((λ x. g (x x)) (λ x. g (x x)))) = g (g (Y g))
. . . . . .
The equivalence
Y g = g (Y g)
is isomorphic to
fix f = f (fix f)
The untyped lambda calculus can encode arbitrary constructive proofs over general/μ-recursive functions.
FACT = λ n. Y FACT' n
FACT' = λ rec n. if n == 0 then 1 else n * rec (n - 1)
FACT 3
= (λ n. Y FACT' n) 3
= Y FACT' 3
= FACT' (Y FACT') 3
= if 3 == 0 then 1 else 3 * (Y FACT') (3 - 1)
= 3 * (Y FACT') (3 - 1)
= 3 * FACT' (Y FACT') 2
= 3 * if 2 == 0 then 1 else 2 * (Y FACT') (2 - 1)
= 3 * 2 * (Y FACT') 1
= 3 * 2 * FACT' (Y FACT') 1
= 3 * 2 * if 1 == 0 then 1 else 1 * (Y FACT') (1 - 1)
= 3 * 2 * 1 * (Y FACT') 0
= 3 * 2 * 1 * FACT' (Y FACT') 0
= 3 * 2 * 1 * if 0 == 0 then 1 else 0 * (Y FACT') (0 - 1)
= 3 * 2 * 1 * 1
= 6
(Multiplication delayed, confluence)
For Churchian untyped lambda calculus, there has been shown to exist a recursively enumerable infinity of fixed-point combinators besides Y.
X = λ f. (λ x. x x) (λ x. f (x x))
Y' = (λ x y. x y x) (λ y x. y (x y x))
Z = λ f. (λ x. f (λ v. x x v)) (λ x. f (λ v. x x v))
Θ = (λ x y. y (x x y)) (λ x y. y (x x y))
. . .
Normal-order beta reduction makes the unextended untyped lambda calculus a Turing-complete rewrite system.
In Haskell, the fixed-point combinator can be elegantly implemented
fix :: forall t. (t -> t) -> t
fix f = f (fix f)
Haskell’s laziness normalizes to a finity before all subexpressions have been evaluated.
primes :: Integral t => [t]
primes = sieve [2 ..]
where
sieve = fix (\ rec (p : ns) ->
p : rec [n | n <- ns
, n `rem` p /= 0])
David Turner: Church's Thesis and Functional Programming
Alonzo Church: An Unsolvable Problem of Elementary Number Theory
Lambda calculus
Church–Rosser theorem
Other answers provide pretty concise answer to this, without one important fact: You don't need to implement fixed point combinator in any practical language in this convoluted way and doing so serves no practical purpose (except "look, I know what Y-combinator is"). It's important theoretical concept, but of little practical value.
Here is a JavaScript implementation of the Y-Combinator and the Factorial function (from Douglas Crockford's article, available at: http://javascript.crockford.com/little.html).
function Y(le) {
return (function (f) {
return f(f);
}(function (f) {
return le(function (x) {
return f(f)(x);
});
}));
}
var factorial = Y(function (fac) {
return function (n) {
return n <= 2 ? n : n * fac(n - 1);
};
});
var number120 = factorial(5);
A Y-Combinator is another name for a flux capacitor.
I have written a sort of "idiots guide" to the Y-Combinator in both Clojure and Scheme in order to help myself come to grips with it. They are influenced by material in "The Little Schemer"
In Scheme:
https://gist.github.com/z5h/238891
or Clojure:
https://gist.github.com/z5h/5102747
Both tutorials are code interspersed with comments and should be cut & pastable into your favourite editor.
As a newbie to combinators, I found Mike Vanier's article (thanks Nicholas Mancuso) to be really helpful. I would like to write a summary, besides documenting my understanding, if it could be of help to some others I would be very glad.
From Crappy to Less Crappy
Using factorial as an example, we use the following almost-factorial function to calculate factorial of number x:
def almost-factorial f x = if iszero x
then 1
else * x (f (- x 1))
In the pseudo-code above, almost-factorial takes in function f and number x (almost-factorial is curried, so it can be seen as taking in function f and returning a 1-arity function).
When almost-factorial calculates factorial for x, it delegates the calculation of factorial for x - 1 to function f and accumulates that result with x (in this case, it multiplies the result of (x - 1) with x).
It can be seen as almost-factorial takes in a crappy version of factorial function (which can only calculate till number x - 1) and returns a less-crappy version of factorial (which calculates till number x). As in this form:
almost-factorial crappy-f = less-crappy-f
If we repeatedly pass the less-crappy version of factorial to almost-factorial, we will eventually get our desired factorial function f. Where it can be considered as:
almost-factorial f = f
Fix-point
The fact that almost-factorial f = f means f is the fix-point of function almost-factorial.
This was a really interesting way of seeing the relationships of the functions above and it was an aha moment for me. (please read Mike's post on fix-point if you haven't)
Three functions
To generalize, we have a non-recursive function fn (like our almost-factorial), we have its fix-point function fr (like our f), then what Y does is when you give Y fn, Y returns the fix-point function of fn.
So in summary (simplified by assuming fr takes only one parameter; x degenerates to x - 1, x - 2... in recursion):
We define the core calculations as fn: def fn fr x = ...accumulate x with result from (fr (- x 1)), this is the almost-useful function - although we cannot use fn directly on x, it will be useful very soon. This non-recursive fn uses a function fr to calculate its result
fn fr = fr, fr is the fix-point of fn, fr is the useful funciton, we can use fr on x to get our result
Y fn = fr, Y returns the fix-point of a function, Y turns our almost-useful function fn into useful fr
Deriving Y (not included)
I will skip the derivation of Y and go to understanding Y. Mike Vainer's post has a lot of details.
The form of Y
Y is defined as (in lambda calculus format):
Y f = λs.(f (s s)) λs.(f (s s))
If we replace the variable s in the left of the functions, we get
Y f = λs.(f (s s)) λs.(f (s s))
=> f (λs.(f (s s)) λs.(f (s s)))
=> f (Y f)
So indeed, the result of (Y f) is the fix-point of f.
Why does (Y f) work?
Depending the signature of f, (Y f) can be a function of any arity, to simplify, let's assume (Y f) only takes one parameter, like our factorial function.
def fn fr x = accumulate x (fr (- x 1))
since fn fr = fr, we continue
=> accumulate x (fn fr (- x 1))
=> accumulate x (accumulate (- x 1) (fr (- x 2)))
=> accumulate x (accumulate (- x 1) (accumulate (- x 2) ... (fn fr 1)))
the recursive calculation terminates when the inner-most (fn fr 1) is the base case and fn doesn't use fr in the calculation.
Looking at Y again:
fr = Y fn = λs.(fn (s s)) λs.(fn (s s))
=> fn (λs.(fn (s s)) λs.(fn (s s)))
So
fr x = Y fn x = fn (λs.(fn (s s)) λs.(fn (s s))) x
To me, the magical parts of this setup are:
fn and fr interdepend on each other: fr 'wraps' fn inside, every time fr is used to calculate x, it 'spawns' ('lifts'?) an fn and delegates the calculation to that fn (passing in itself fr and x); on the other hand, fn depends on fr and uses fr to calculate result of a smaller problem x-1.
At the time fr is used to define fn (when fn uses fr in its operations), the real fr is not yet defined.
It's fn which defines the real business logic. Based on fn, Y creates fr - a helper function in a specific form - to facilitate the calculation for fn in a recursive manner.
It helped me understanding Y this way at the moment, hope it helps.
BTW, I also found the book An Introduction to Functional Programming Through Lambda Calculus very good, I'm only part through it and the fact that I couldn't get my head around Y in the book led me to this post.
Here are answers to the original questions, compiled from the article (which is TOTALY worth reading) mentioned in the answer by Nicholas Mancuso, as well as other answers:
What is a Y-combinator?
An Y-combinator is a "functional" (or a higher-order function — a function that operates on other functions) that takes a single argument, which is a function that isn't recursive, and returns a version of the function which is recursive.
Somewhat recursive =), but more in-depth definition:
A combinator — is just a lambda expression with no free variables.
Free variable — is a variable that is not a bound variable.
Bound variable — variable which is contained inside the body of a lambda expression that has that variable name as one of its arguments.
Another way to think about this is that combinator is such a lambda expression, in which you are able to replace the name of a combinator with its definition everywhere it is found and have everything still work (you will get into an infinite loop if combinator would contain reference to itself, inside the lambda body).
Y-combinator is a fixed-point combinator.
Fixed point of a function is an element of the function's domain that is mapped to itself by the function.
That is to say, c is a fixed point of the function f(x) if f(c) = c
This means f(f(...f(c)...)) = fn(c) = c
How do combinators work?
Examples below assume strong + dynamic typing:
Lazy (normal-order) Y-combinator:
This definition applies to languages with lazy (also: deferred, call-by-need) evaluation — evaluation strategy which delays the evaluation of an expression until its value is needed.
Y = λf.(λx.f(x x)) (λx.f(x x)) = λf.(λx.(x x)) (λx.f(x x))
What this means is that, for a given function f (which is a non-recursive function), the corresponding recursive function can be obtained first by computing λx.f(x x), and then applying this lambda expression to itself.
Strict (applicative-order) Y-combinator:
This definition applies to languages with strict (also: eager, greedy) evaluation — evaluation strategy in which an expression is evaluated as soon as it is bound to a variable.
Y = λf.(λx.f(λy.((x x) y))) (λx.f(λy.((x x) y))) = λf.(λx.(x x)) (λx.f(λy.((x x) y)))
It is same as lazy one in it's nature, it just has an extra λ wrappers to delay the lambda's body evaluation. I've asked another question, somewhat related to this topic.
What are they good for?
Stolen borrowed from answer by Chris Ammerman: Y-combinator generalizes recursion, abstracting its implementation, and thereby separating it from the actual work of the function in question.
Even though, Y-combinator has some practical applications, it is mainly a theoretical concept, understanding of which will expand your overall vision and will, likely, increase your analytical and developer skills.
Are they useful in procedural languages?
As stated by Mike Vanier: it is possible to define a Y combinator in many statically typed languages, but (at least in the examples I've seen) such definitions usually require some non-obvious type hackery, because the Y combinator itself doesn't have a straightforward static type. That's beyond the scope of this article, so I won't mention it further
And as mentioned by Chris Ammerman: most procedural languages has static-typing.
So answer to this one — not really.
A fixed point combinator (or fixed-point operator) is a higher-order function that computes a fixed point of other functions. This operation is relevant in programming language theory because it allows the implementation of recursion in the form of a rewrite rule, without explicit support from the language's runtime engine. (src Wikipedia)
The y-combinator implements anonymous recursion. So instead of
function fib( n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }
you can do
function ( fib, n ){ if( n<=1 ) return n; else return fib(n-1)+fib(n-2) }
of course, the y-combinator only works in call-by-name languages. If you want to use this in any normal call-by-value language, then you will need the related z-combinator (y-combinator will diverge/infinite-loop).
The this-operator can simplify your life:
var Y = function(f) {
return (function(g) {
return g(g);
})(function(h) {
return function() {
return f.apply(h(h), arguments);
};
});
};
Then you avoid the extra function:
var fac = Y(function(n) {
return n == 0 ? 1 : n * this(n - 1);
});
Finally, you call fac(5).
I think the best way to answer this is to pick a language, like JavaScript:
function factorial(num)
{
// If the number is less than 0, reject it.
if (num < 0) {
return -1;
}
// If the number is 0, its factorial is 1.
else if (num == 0) {
return 1;
}
// Otherwise, call this recursive procedure again.
else {
return (num * factorial(num - 1));
}
}
Now rewrite it so that it doesn't use the name of the function inside the function, but still calls it recursively.
The only place the function name factorial should be seen is at the call site.
Hint: you can't use names of functions, but you can use names of parameters.
Work the problem. Don't look it up. Once you solve it, you will understand what problem the y-combinator solves.

Resources