Are Services superior to Free Monads?
A recurring hot topic in the functional programming world is how to make your code scale while keeping professionnal level of code quality.
Quite often in the functional programming we communities and talk people are focusing on enhancing specifics…
To organise your code in a functional paradigm there are many concurrent proposals. And structuring a code application is challenging. The way you need to structure the code generally need to reach a few properties.
You should make it easy to test your code
You need to support modern features any modern application is expected to provide. Typically ability to write logs, if possible send structured logs events.
The code should try to help people focalise on the business logic and put aside irrelevant technical details.
Split your applications into smaller (ideal composable) components
Control accesses between different components of your applications
The design space is quite open. In Haskell for example, there are different proposed solutions.
One of my preferred one to start with is the Handler Pattern1. Because it doesn't need any advanced Haskell knowledge to understand. And also it prevents a classical overabstraction haskell curse I often see within Haskellers. No premature abstraction here. No typeclass.
The main principle behing it is that you create handlers. Handlers are component focused that each provide a set of methods and functions already initialized.
Monads, MTL, RIO, Handler Pattern, Free Monad
There are a lot of solutions to architecture a program while keeping all the best properties of functional programming as well as best professional practices.
Here too, there are different level of looking at the problem of code organisation. On the very high level, an application is often understood as a set of features. But for all of thoses features to work together it is generally a lot of work to organise them.
So we can descend the level to look at code organisation. Files organisation, how to group them. Structure of the code organisation. How to put test, etc…
If you strive for composability you generally try to understand how to group "components" and ask yourselve what a componentn should contain. Here is a solution.
Free Monads/Effect System
Foreword, semantic vs syntax.
The kind of best way to talk about semantic and forget about the syntax is to deal directly with a simplified representation of the AST.
(interpret-with [effect-1 effect-2 ... effect-n] (let [admin-user (get-in-config [:user :admin :user-id]) admin (get-user admin-user-id) admin-email (get admin :email)] (log "Admin email" admin-email) admin-email))
It will be up to the actual instanciation of all
effect-* to change the
interpretation of the body.
So some effect could have different interpreation of specific symbols.
So here we can imagine that
handlers specified in the effects.
One advantage is that to test your code you can simply use stubbed effects. One can use a list users
Real effects and free monads are in fact more powerful than this example
For example, within a free monad, even
let semantic would be changed.
But let's not take this rabbit hole in this article right now.