All natural numbers
In Category Theory identity it’s just an arrow that starts from the object and ends to it.
Somehow the object and the subject are the same. And today we start with a simple scenario. We want to order all natural numbers.
Ok, at least those defined as Int32, so that we start from int.MinValue and we end at int.MaxValue. The relation of order is “less than or equal to”, or in symbols ≤.
It’s clear that we have constructed a simple Category, a ≤ b is a Morphism between numbers (i.e. 2≤3) and composition, identity, and associative law are enforced.
How can we represent in C# a category? We could use an interface:
public interface ICategory<TObject, TMorphism>
{
IEnumerable<TObject> Objects { get; }
TMorphism Morphism(TObject first, TObject second);
TMorphism Compose(TMorphism morphism2, TMorphism morphism1);
TMorphism Identity(TObject @object);
}
The objects are a collection that exposes an enumerator, which supports a simple iteration over a non-generic collection. The reason is clear: can we imagine to represent an infinite set of values, like all the natural numbers with the finite resource of a computer?
C# cannot speed the creation of the objects since it has just an iterator. If we consider the Category of the Int32 in .net world we could have:
public IEnumerable<Expression> Objects
{
get
{
for (int int32 = _init; int32 <= _end; int32++)
{
yield return Expression.Constant(int32);
}
}
}
An expression represents a strongly typed lambda expression. The .net compiler converts the lambda expression which is assigned to Expression<TDelegate> into an Expression Tree instead of executable code. This expression tree is used by remote LINQ query providers as a data structure to execute logic out of it.
A Morphism si defined as:
Y <= Z
public BinaryExpression Morphism(Expression @objectLeft, Expression objectRight)
{
return Expression.LessThanOrEqual(@objectLeft, @objectRight);
}
The composition requires only two binary expressions, for instance:
(Y <= Z) [(X <= Y)] => X <= Z.
public BinaryExpression Compose(BinaryExpression morphism2, BinaryExpression morphism1) =>
Morphism(morphism1.Left, morphism2.Right);
Also identity it’s a morphism of an object on itself.
public BinaryExpression Identity(Expression @object)
{
return Morphism(@object, @object);
}
Unit testing is quite easy and forthcoming since the compile method can be used to convert a Lambda Expression tree into the delegate that it represents:
[DataTestMethod]
[DataRow(1)]
[DataRow(-3)]
[DataRow(0)]
public void Identity_ShouldBeEqualToItself_True(int a)
{
var expression = int32Category.Identity(Expression.Constant(a));
var result = Expression.Lambda<Func<bool>>(expression).Compile()();
Assert.IsTrue(result);
}
Also .ToString() can be used to return the whole expression as a string.
[DataTestMethod]
[DataRow(1, 5, 7)]
[DataRow(-5, -1, 0)]
public void Compose_ShouldCompose_AreEqual(int a, int b, int c)
{
var expression1 = int32Category.Morphism(Expression.Constant(a), Expression.Constant(b));
var expression2 = int32Category.Morphism(Expression.Constant(b), Expression.Constant(c));
var expression = int32Category.Compose(expression2, expression1);
Assert.AreEqual(expression.ToString(), $"({a} <= {c})");
}
Finally, we have shown that the relevance of Category Theory shines everywhere, from LINQ to pure functional programming.
For the code in the article you will find everything here:
Recommended by LinkedIn
Empowering Businesses with Conversational & Generative AI, CX Excellence, Cloud Solutions, Digital Transformation, Enterprise Integration, and AI Business Automation | VP Digital Solutions @ Pronix Inc
1yThe concept of ordering natural numbers within a given range is great to bring back my school mathematics memories! I love how it finds the principles of composition, identity, and associative law.