DEV Community

Voltra
Voltra

Posted on

Free Monads for smart optimized code

One of the most annoying and complex problem to solve is database querying. When your request is not a simple read or write, it becomes quite complicated to be fully optimal.

Most of the time, it's due to technical constraints (e.g. a library used makes multiple independent requests instead of batching them somehow).

What if we could eliminate the problem altogether?

My proposed solution? Turn your whole application logic into Free Monad program.

Introducing Free Monads: cool monads that help building eDSL.

The whole idea is that you make sort of "programs" that are really blueprints for an execution. What makes it extremely interesting is that you can evaluate the same program differently, it's the evaluator that dictates how things work, not the program. The program only has the "shape" of the instructions.

How is that different from interfaces in OOP you might ask? It's simple, with interfaces you're still operating at a value level. With Free Monad, you're operating at an operation level.

In a way, you can think of Free Monad programs as a sort of weird AST, and evaluators as visitors.

Here's the proposed pseudo code:

function runApp($request) {
  $program = new AppProgram($request);
  try {
    $dbEvaluator = new DbAppEvaluator();
    $queryData = $dbEvaluator->evaluate($program);
    $responseEvaluator = new ResponseEvaluator($queryData);
    return $responseEvaluator->evaluate($program);
  } catch($e) {
    $errorHandlerEvaluator = new ErrorHandlerEvaluator($e);
    return $errorHandlerEvaluator->evaluate($program);
  }
}
Enter fullscreen mode Exit fullscreen mode

How cool would that be?

Things like Database::connect() wouldn't actually give you a connection object back, but a handle to an operation that has been added to the sequence of the program.

Thing like Query::table("x")->select("*")->where($cond) wouldn't immediately query to the database, but be an handler. Then the database evaluator would get all the queries, optimize them, and do as little work as possible.

A whole framework designed like that would eliminate a lot of poor design choices or bad coding practices that lead to poor performances.

Top comments (0)