Lambda Calculus via C# (3) Fundamentals - Function composition

[LINQ via C# series]

[Lambda Calculus via C# series]

Latest version: https://weblogs.asp.net/dixin/lambda-calculus-via-c-1-fundamentals

It may not be the best place to discuss function composition in the lambda calculus series. However, function composition will be used a lot in later articles, so here is a brief introduction.

Function composition

Function composition means to combine simple functions into a more complicated function. The composition of f1 and f2 is defined as: f2 ∘ f1. This new function’s application is:

(f2 ∘ f1) x := f2 (f1 x)

Here the function names f1 and f2 imply the order of being applied. f2 ∘ f1 can also be read as f2 after f1.

Again, it is perfectly nature normal thing to chain 2 function application together, by using the first function’s output as the second function’s input:

double x = 1;
double y = Math.Sqrt(Math.Abs(x));

The following is a more complicated function, combined by 2 simple functions:

Func<double, double> absAndSqrt = x => Math.Sqrt(Math.Abs(x));

So absAndSqrt is a composition of Math.Abs and Math.Sqrt.

Generally, a function of type Func<T1, T2> and a function of type Func<T2, T3> can be composed to a new function of type Func<T1, T3>:

public static partial class FuncExtensions
{
    public static Func<T1, T3> o<T1, T2, T3>
        (this Func<T2, T3> function2, Func<T1, T2> function1) => 
            arg => function2(function1(arg));
}

Unfortunately, in C# there is no place to define custom function operators, so extension method has to be used. This method is named o to mimic the ∘ operator. Also, in lambda calculus, functions are curried,  so this one extension method is good enough.

Built-in operator in other languages

It is common for other functional language to have a built in function composition operator. In Haskell, ∘ is just dot (.):

(.) :: (b -> c) -> (a -> b) -> a -> c
f2 . f1 = \x -> f2 (f1 x)

And F# has >>:

let inline (>>) f1 f2 x = f2 (f1 x)

It is called forward composition. So there is also a backward composition operator <<:

let inline (<<) f2 f1 x = f2 (f1 x)

Properties

Function composition has 2 important properties

Associativity

Function composition is associative. That means (f3 ∘ f2) ∘ f1 and f3 ∘ (f2 ∘ f1) are the same.

When applying x to (f3 ∘ f2) ∘ f1,  according to the definition of ∘:

  ((f3 ∘ f2) ∘ f1) (x)
≡ (f3 ∘ f2) (f1 (x))
≡ f3 (f2 (f1 (x)))

And when applying x to f3 ∘ (f2 ∘ f1):

  f3 ∘ (f2 ∘ f1)
≡ f3 ∘ (f2 (f1 (x)))
≡ f3 (f2 (f1 (x)))

So they lead to identical result. In C#, this means f3.o(f2).o(f1) and f3.o(f2.o(f1)) are the same.

Unit

There is a unit function for function composition:

Id := λx.x

so that:

f ∘ Id ≡ f

and

Id ∘ f ≡ f

In C#, Id is:

public static partial class FuncExtensions
{
    public static T Id<T>
        (T value) => value;
}

1 Comment

Add a Comment

As it will appear on the website

Not displayed

Your website