Recursive Lambda with Fixed Point Generator

Reading Mads Torgersen old blog post on Recursive Lambda Expressions, I decided it was time for me to seriously play with his code and try out the fixed point generator to create recursive lambda expressions (together with the fact that I was sick and felt bored).

Taking lessons from that blog post, I created a reusable fixed point generator which we can use for anything that uses recursion. Here's the code, simply.

   1:  public static Func<T, T> Fix<T>(Func<Func<T, T>, Func<T, T>> F)
   2:  {
   3:     return x => F(Fix<T>(F))(x);
   4:  }
   6:  public static Func<T, T, T> Fix<T>(Func<Func<T, T, T>, Func<T, T, T>> F)
   7:  {
   8:     return (x, n) => F(Fix<T>(F))(x, n);
   9:  }
  11:  public static Func<T1, T2, T1> Fix<T1, T2>(Func<Func<T1, T2, T1>, Func<T1, T2, T1>> F)
  12:  {
  13:     return (x, n) => F(Fix<T1, T2>(F))(x, n);
  14:  }
  16:  public static Func<T, T, T, T> Fix<T>(Func<Func<T, T, T, T>, Func<T, T, T, T>> F)
  17:  {
  18:     return (x, n, k) => F(Fix<T>(F))(x, n, k);
  19:  }

Static Fix methods are the actual Fixed Point Generator as described in Mads' blog. This simplifies the code and makes it reusable. The method at lines 11-14 shows how 2 different input can be used. I will be using this method for the sine and cosine lambda expressions I've written.

   1:  Func<double, double> factorial = Fix<double>(fac => x => x == 0 ? 1 : x * fac(x - 1));
   2:  Func<double, int, double> sine = Fix<double, int>(sin => (x, n) => n == 0 ? x : 
   3:      sin(x, n - 1) + Math.Pow(-1, n) * Math.Pow(x, 2 * n + 1) / factorial(2 * n + 1));
   4:  Func<double, int, double> cosine = Fix<double, int>(cos => (x, n) => n == 0 ? 1 : 
   5:      cos(x, n - 1) + Math.Pow(-1, n) * Math.Pow(x, 2 * n) / factorial(2 * n));

The factorial lambda expression is the same as in Mads' blog. I've created both sine and cosine lambda expressions learning from how the fixed point generator works. I have to keep factorial as double instead of int because it'll make the precision wrong.

I used the Taylor Series in order to generate the sine and cosine function. x is the angle in radians, and n is the number of recursion to do (i.e. the more recursion, the more precision).

The basic recursion is as follows:

So that's that! Plug in your lambda expression into the Fix static method and you're done, you've got recursion.

Further testing out whether if it actually works, here's a simple testing code:

   1:  for (int i = 0; i < 20; i++)
   2:  {
   3:     Console.WriteLine(factorial(i));
   4:  }
   6:  Console.WriteLine(sine(Math.PI / 4, 10));
   7:  Console.WriteLine(Math.Sin(Math.PI / 4));
   9:  Console.WriteLine(cosine(Math.PI / 3, 10));
  10:  Console.WriteLine(Math.Cos(Math.PI / 3));
  11:  Console.ReadKey();

Here, what I do is I check my sine and cosine output with the actual Math.Sin and Math.Cos methods from the framework. It looks like it works well with n = 10 or higher, achieving the same precision as the framework.

That's that. I will play around with more of this, and create more methods out of this.

I tried generalizing the method itself to make it look better and easier to read, but the limits of Generics in C# stopped me from doing anything further. Here's what I tried to do, but failed of course.

   1:  // I need a constraint operator- to make this work, but Generics does not support this
   2:  public static Func<T, T> Factorial<T>() where T : struct, IEquatable<T>, operator-
   3:  {         
   4:      return Fix<T>(fac => x => x.Equals(0) ? 1 : x * fac(x - 1));
   5:  }

If that was successful, then the code would have been reduced to simply like this.

   1:  Factorial(5)

Doesn't that look better? If only, but there must be come other way to do this.