DEV Community

Iven Marquardt
Iven Marquardt

Posted on • Edited on

More Type Safe and Descriptive Compositions in an Untyped Setting

Functional programming is about composition. Besides normal function composition there is a rich variety of composition types. Let us take a look at functions of shape <A>(_: A) => Boolean. In math such functions are called predicates and come from logic.

At first sight it looks like we cannot compose predicates. However, they form a monoid, which is an algebraic structure that formally describes the process of combining things. Combining two predicates is the composition we are looking for:

const record = (type, o) =>
  (o[type.name || type] = type.name || type, o);

const Pred = pred => record(Pred, {pred});

const predAppend = tp => tq =>
  Pred(x => tp.pred(x) && tq.pred(x));

const predEmpty = () => Pred(_ => true);

const numLte_ = y => x => x <= y;

const numGte_ = y => x => x >= y;

const isEven = x => (x & 1) === 0;

const numBetween = (x, y) =>
  predAppend(
    Pred(numLte_(y)))
      (Pred(numGte_(x)));

const main = predAppend(
  numBetween(5, 10))
    (Pred(isEven));

main.pred(6); // true
main.pred(7); // false
main.pred(12); // false

run code

Using the monoid we can build arbitrarily complex rule engines out of simple predicates.

Pred seems to be only a simple object wrapper but it adds type safety to our code, because we cannot use predicates in lieu of normal functions anymore or in a scenario, where booleans are meant to be combined with the || operator. Moreover it makes our code more descriptive, because predicates are denoted explicitly.

As functional programmers we do this not only with Pred but also with numerous other types. This has an SYSTEMIC EFFECT on our code, especially for a larger code base. Imagine how type safe and declarative it gets.

Read more on functional programming in Javascript in my online course.

Top comments (0)