110 lines
3.8 KiB
Org Mode
110 lines
3.8 KiB
Org Mode
#+TITLE: Are Services superior to Free Monads?
|
|
#+AUTHOR: Yann Esposito
|
|
#+EMAIL: yann@esposito.host
|
|
#+DATE: [2021-01-10 Sun]
|
|
#+KEYWORDS: haskell, clojure, architecture, programming
|
|
#+DESCRIPTION: Here is a simple description on how to architect a big functional programming application.
|
|
#+OPTIONS: auto-id:t toc:nil
|
|
|
|
#+begin_abstract
|
|
TODO
|
|
#+end_abstract
|
|
|
|
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.
|
|
|
|
1. You should make it easy to test your code
|
|
2. You need to support modern features any modern application is expected
|
|
to provide. Typically ability to write logs, if possible send structured
|
|
logs events.
|
|
3. The code should try to help people focalise on the business logic and
|
|
put aside irrelevant technical details.
|
|
4. Split your applications into smaller (ideal composable) components
|
|
5. 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
|
|
Pattern[fn:handler_pattern].
|
|
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.
|
|
|
|
[fn:handler_pattern]: https://jaspervdj.be/posts/2018-03-08-handle-pattern.html
|
|
|
|
* Monads, MTL, RIO, Handler Pattern, Free Monad
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: monads--mtl--rio--handler-pattern--free-monad
|
|
:END:
|
|
|
|
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
|
|
:PROPERTIES:
|
|
:CUSTOM_ID: free-monads-effect-system
|
|
:END:
|
|
|
|
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.
|
|
|
|
|
|
Overall API:
|
|
|
|
#+begin_src clojure
|
|
(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))
|
|
#+end_src
|
|
|
|
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 =get-in-config=, =get-user= and =log= are
|
|
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
|
|
is showing.
|
|
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.
|