Implementation

Our engine is written in Scala, with the addition of Shapeless library.

Before we look at some example code, we need to get some basic understanding of generic programming and ADT.

What are ADTs (Algebraic Data Types)? “Shapeless guide” says:

Algebraic data types (ADTs) are a functional programming concept with a fancy

name but a very simple meaning. They are an idiomatic way of representing

data using “ands” and “ors”.

The code below shows ADTs differentiating between bank account types:

Account is SavingsAccount OR CheckingAccount, and SavingsAccount has amount AND forHowLong. In more formal terminology:

‘or’ types (Account) are called Coproducts.

‘and’ types (SavingsAccount and CheckingAccount) are called Products,

We use ADTs because they are safeguarded by Scala Exhaustiveness Checking. For example, let’s say we write the code below:

Scala compile would warn us of a missing implementation:

match may not be exhaustive.

It would fail on the following input: BussinesAccount(_)

Let’s now look at some example code.

Building a model

Let’s start with defining some random facts about our users, such as whether they like ice cream 😋:

And some available operators, such as greater than, lower than etc:

And some available values:

Operator “:+:” is syntactic sugar for creating generalized Either with arbitrary number of available options. It means that ValueType can be either one of defined types. For more information about shalepess Coproducts visit project website.

Now that we have a model, we can define a test case:

With all definitions ready we can implement the decision engine in the following way:

Now we can define test cases which can be run against some facts. The code below shows data about our users (whether they like ice cream, how many times they logged in last month etc.) and separates them into buckets depending on which criteria they do or don’t satisfy.