466 words
2 minutes
Lambda Calculus via C# (14) Church Pair (2-Tuple) and Church Numeral Decrease

[LINQ via C# series]#

[Lambda Calculus via C# series]#

Latest version: https://weblogs.asp.net/dixin/lambda-calculus-via-csharp-4-tuple-and-signed-numeral#

In the Church numeral arithmetic part, the Decrease was defined as:

Decrease := λn.λf.λx.n (λg.λh.h (g f)) (λu.x) (λu.u)

This is complex. Now with Church pair (called tuple here to align to C# terms), Decrease can be defined in a easier way.

Shift a Church Pair (2-Tuple)#

First, a function is needed to shift a tuple:

Shift = λf.λt.CreateTuple (Item2 t) (f (Item1 t))

It takes a tuple (x, y) and a function f, then returns a new tuple (y, f y).

C# implementation is:

// (x, y) -> (y, f(y))
// Shift = tuple => f => Create(tuple.Item2())(f(tuple.Item1()))
public static Tuple<T, T> Shift<T>
(this Tuple<T, T> tuple, Func<T, T> f) => Create<T, T>(tuple.Item2())(f(tuple.Item2()));

Again, the implementation is uncurried extension method for convenience of application, and readability.

Decrease a Church numeral#

Remember a Church numeral n can be considered to do “Increase” n times from 0:

n Increase Zero
≡ n

What if doing “Shift” n times base on (0, 0)?

3 (Shift Increase) (0, 0)
≡ (Shift Increase) ∘ (Shift Increase) ∘ (Shift Increase) (0, 0)
≡ (Shift Increase) ∘ (Shift Increase) (0, Increase 0)
≡ (Shift Increase) ∘ (Shift Increase) (0, 1)
≡ (Shift Increase) ∘ (1, Increase 1)
≡ (Shift Increase) ∘ (1, 2)
≡ (2, Increase 2)
≡ (2, 3)

And generally:

n (Shift Increase (0, 0))
≡ (n - 1, n)

This turns out a way to get the predecessor of n. So:

Decrease2 := λn.Item1 (n (Shift Increase) (CreateTuple 0 0))

And C#:

public static partial class _NumeralExtensions
{
// Decrease2 = n => n(tuple => tuple.Shift(Increase))(ChurchTuple.Create(Zero)(Zero)).Item1();
public static _Numeral Decrease2
(this _Numeral numeral) =>
numeral.Numeral<Tuple<_Numeral, _Numeral>>()
(tuple => tuple.Shift(Increase)) // (x, y) -> (y, y + 1)
(ChurchTuple.Create<_Numeral, _Numeral>(Zero)(Zero))
.Item1();
}

Unit tests#

The following unit tests also shows how to apply the uncurried methods Swap, Shift, _Create:

[TestClass()]
public class ChurchTupleTests
{
[TestMethod()]
public void CreateItem1Item2Test()
{
Tuple<int, string> tuple1 = ChurchTuple.Create<int, string>(1)("a");
Assert.AreEqual(1, tuple1.Item1());
Assert.AreEqual("a", tuple1.Item2());
Tuple<string, int> tuple2 = ChurchTuple.Create<string, int>("a")(1);
Assert.AreEqual("a", tuple2.Item1());
Assert.AreEqual(1, tuple2.Item2());
object @object = new object();
Tuple<object, int> tuple3 = ChurchTuple.Create<object, int>(@object)(1);
Assert.AreEqual(@object, tuple3.Item1());
Assert.AreEqual(1, tuple3.Item2());
}
[TestMethod()]
public void ShiftTest()
{
Tuple<int, int> tuple1 = ChurchTuple.Create<int, int>(1)(2).Shift(_ => _);
Assert.AreEqual(2, tuple1.Item1());
Assert.AreEqual(2, tuple1.Item2());
Tuple<int, int> tuple2 = ChurchTuple.Create<int, int>(2)(3).Shift(value => value * 2);
Assert.AreEqual(3, tuple2.Item1());
Assert.AreEqual(6, tuple2.Item2());
Tuple<string, string> tuple3 = ChurchTuple.Create<string, string>("a")("b").Shift(value => value + "c");
Assert.AreEqual("b", tuple3.Item1());
Assert.AreEqual("bc", tuple3.Item2());
}
[TestMethod()]
public void SwapTest()
{
Tuple<int, string> tuple1 = ChurchTuple.Create<string, int>("a")(1).Swap();
Assert.AreEqual(1, tuple1.Item1());
Assert.AreEqual("a", tuple1.Item2());
Tuple<string, int> tuple2 = ChurchTuple.Create<int, string>(1)("a").Swap();
Assert.AreEqual("a", tuple2.Item1());
Assert.AreEqual(1, tuple2.Item2());
object @object = new object();
Tuple<object, int> tuple3 = ChurchTuple.Create<int, object>(1)(@object).Swap();
Assert.AreEqual(@object, tuple3.Item1());
Assert.AreEqual(1, tuple3.Item2());
}
[TestMethod()]
public void _CreateTest()
{
Tuple<int, string> tuple1 = ChurchTuple._Create(1, "a");
Assert.AreEqual(1, tuple1.Item1());
Assert.AreEqual("a", tuple1.Item2());
Tuple<string, int> tuple2 = ChurchTuple._Create("a", 1);
Assert.AreEqual("a", tuple2.Item1());
Assert.AreEqual(1, tuple2.Item2());
object @object = new object();
Tuple<object, int> tuple3 = ChurchTuple._Create(@object, 1);
Assert.AreEqual(@object, tuple3.Item1());
Assert.AreEqual(1, tuple3.Item2());
}
}
Lambda Calculus via C# (14) Church Pair (2-Tuple) and Church Numeral Decrease
https://dixin.github.io/posts/lambda-calculus-via-c-sharp-14-church-pair-2-tuple-and-church-numeral-decrease/
Author
Dixin
Published at
2018-11-14
License
CC BY-NC-SA 4.0