The K-Combinator in Practice

Photograph by Sepand Bakhtiari, CC BY-SA 4.0, via Wikimedia Commons

The K-Combinator

Combinators are functional patterns that glue (AKA compose) together functions. These patterns promote single responsibility and decoupling.

The K-Combinator is more commonly known as the Constant Combinator. It is formally known as the Kestrel Combinator. The K-Combinator can be defined in C# as:

Func<dynamic, T> Constant<T>(T x) => _ => x;

It's a function that always returns the initial value when called with any input. In a sense, it is a mapping of the set of all values to x. Simple!

Side Effects

One common pattern I've seen this used is in the implementation of the Tee function. Tee is a way of causing side effects in a pipeline of functions. This can aide in code readability by keeping your control flow in top to bottom direction, while explicitly communicating that a side effect is happening.

Func<T, T> Tee<T>(Action sideEffect)
  => input 
    => Constant<T>(input)(sideEffect.Invoke(input));

// sometime later...

var ItemForSale = ...
var ExecutePayment = Tee((total) => ProcessTransaction(total));

var Total = ExecutePayment(CalculateTotal(ItemForSale));

In this case, the Tee would process the transaction, while passing the input as the result. Using this in combination with the T-combinator ( See Part I in this series ) and you can get something like this:

var Total = ItemForSale
  .Pipe(CalculateTotal)
  .Pipe(ExecutePayment)

// renaming Pipe to Then

var Total = ItemForSale.
  Then(CalculateTotal).
  Then(ExecutePayment)

In the end, what it buys you is:

  • decoupling of functions
  • code that reads from top to bottom
  • lazy evaluation of side effects

Awesome!

No Comments Yet