Розробка веб-сервісів чистим функційним способом є нетривіальною задачею через те, що там зазвичай наявні виклики бази даних на всіх етапах обробки запиту сервера, що ускладнює виокремлення функційного ядра коду, а це є основним принципом розробки функційної архітектури програми. Цю публікацію
присвячено вирішенню цієї проблеми вільними монадами, за допомогою яких код, що працює зі змінними
даними, можна розділити на функційне представлення імперативних операцій, що визначаються створеними на базі вільних монад предметно-орієнтованими мовами програмування (англ. Domain-Specific
Language, DSL), та інтерпретатор, що власне виконує ці операції. У статті наведено основні принципи
використання вільних монад та їхні переваги в контексті задачі розробки HTTP-сервісу.
Implementing web-services in a pure functional way is not a trivial task, because it is common to a query
database (or a different type of mutable data store) on all the stages of the server request processing.
This complicates separation of the pure functional core and imperative shell of the program, which is
the primary principle of the functional software architecture. This article focuses on resolving this problem by
using free monads, which makes it possible to implement a new domain-specific language that is defined by
purely functional data structures, to describe imperative operations. Each operation is later interpreted into
actual data mutation by an interpreter. This allows defining the algorithms as a combination of atomic DSL
operations, which may have side-effects, in a purely functional way, while only the interpretation logic of
those operations remains imperative.
In contrast to a standard approach, the amount of the imperative code in free monad based algorithms
scales depending on the number of atomic DSL operations instead of the size of the whole program.
This can bring a big difference, especially if atomic operations are frequently re-used.
As part of the research, an HTTP-based message exchange service was implemented in its own free
monad based domain-specific language. As a basis, functional programming language Scala was used.
The article shows the implementation of the server endpoint that sends the message to a specific conversation.
The endpoint implementation consists of many atomic database queries and contains multiple branches of
the control flow.
First, each atomic database query or group of related queries is described as a pure functional record
where dynamic query parameters are defined as values of the record fields. Then, using a free monad
constructor, these operators are upgraded to monads and get the combination logic from the already existing
monadic instances. Usually either one is used as a basis, since it provides a convenient way to handle
exceptions. Next, atomic monadic operations are combined into algorithms. Most functional languages
have syntactic sugar to write expressions, which combine multiple monads. In case of Scala, it is a forexpression.
To interpret a DSL-based expression, an interpreter should be declared and used. The interpreter
is a function with a defined behaviour for atomic DSL operations which are defined earlier. This behaviour
may not be purely functional and may have side effects.
The conducted research confirms that the usage of free monad based functional domain-specific
programming languages is suitable in context of implementing HTTP-services, and it may significantly
decrease the amount of the imperative code.