A docker client with Free Monad in Scala
If you are totally newcomer to Free Monad, Free Monads Are Simple is a good point to start and you can see this link which contains some resources just for this topic.
To put in a nutshell, the Free Monad is a way to describe a program which can be run by an interpreter and is free to interpretation and the exact implementation can be developed later.
In this tutorial, I want to develop a simple Docker client by using cats-free package, that can run the following program:
For simplicity, I want to only support these five operations, The first step is defining an algebra that presents the program.
Pull
: Pulls an image from the repositoryRun
: Runs a containerExec
: Executes command in a container and returns the command outputKill
: Kills a containerRemove
: Removes a container
Now we need to define a DSL
which makes the code more readable and expressive.
These helper methods create free monad wrappers the defined actions, by lifting DockerOperation[A]
to Free[DockerOperation, A]
Now we are able to describe our program as I did at the beginning of the post. but for executing a program we need an interpreter.
To do that we need a Natural Transformation, this transformation would be written as FunctionK[F,G]
or using the symbolic alternative as F ~>
G.
Here, I want to use Spotify’s docker-client package and I am going to create a transformation from DockerOprtation[A] ~> Try[A]
but you can create another interpreter which works for instance with docker API directly and can create another transformation like DockerOperation[A] ~> Future[A]
.
And finally, we can run our program.Free[_]
is just a recursive structure like a sequence of operations producing other operations. For running it we need to call foldMap
method.
You can find the whole source code in the following Link: https://gist.github.com/alirezameskin/bc1b34bb022fc34f77772cdaf063d1eb
Summary
Summing up, Free Monad is definitely a concept that makes it possible to write functional code in an easy and composable way. It is really useful when you want to develop a library.