path: root/site/opinions/
diff options
authorThomas Letan <>2020-08-30 21:34:09 +0200
committerThomas Letan <>2020-08-30 21:35:13 +0200
commit4393865bb75e4b89b1ea9b07c515c7d55505ad1a (patch)
treee01b3c7d9ea745858f3a09226ddf50409b528ee9 /site/opinions/
parent23e5c85eea4d7c7086392ca4b14e097682cb3829 (diff)
Introducing the Opinions page
Diffstat (limited to 'site/opinions/')
1 files changed, 78 insertions, 0 deletions
diff --git a/site/opinions/ b/site/opinions/
new file mode 100644
index 0000000..7296f08
--- /dev/null
+++ b/site/opinions/
@@ -0,0 +1,78 @@
+<h1>Monad Transformers are a Great Abstraction</h1>
+<p>This article has originally been published on <span
+id="original-created-at">July 15, 2017</span>.</p>
+#+OPTIONS: toc:nil
+<div id="history">site/opinions/</div>
+Monads are hard to get right. I think it took me around a year of Haskelling to
+feel like I understood them. The reason is, to my opinion, there is not such
+thing as /the/ Monad. It is even the contrary. When someone asks me how I would
+define Monads in only a few words, [[][I say Monad is a convenient formalism to
+chain specific computations]]. Once I’ve got that, I started noticing “monadic
+construction” everywhere, from the Rust ~?~ operator to the [[][Elixir ~with~
+Haskell often uses another concept above Monads: Monad Transformers. This allows
+you to work not only with /one/ Monad, but rather a stack. Each Monad brings its
+own properties and you can mix them into your very own one. That you can’t have
+in Rust or Elixir, but it works great in Haskell. Unfortunately, it is not an
+easy concept and it can be hard to understand. This article is not an attempt to
+do so, but rather a postmortem review of one situation where I found them
+extremely useful. If you think you have understood how they work, but don’t see
+the point yet, you might find here a beginning of answer.
+Recently, I ran into a very good example of why Monad Transformers worth it. I
+have been working on a project called [[][ogma]] for a couple years now. In a
+nutshell, I want to build “a tool” to visualize in time and space a
+storytelling. We are not here just yet, but in the meantime I have wrote a
+software called ~celtchar~ to build a novel from a list of files. One of its
+newest feature is the choice of language, and by extension, the typographic
+rules. This information is read from a configuration file very early in the
+program flow. Unfortunately, its use comes much later, after several function
+In Haskell, you deal with that kind of challenges by relying on the Reader
+Monad. It carries an environment in a transparent way. The only thing is, I was
+already using the State Monad to carry the computation result. But that’s not an
+issue with the Monad Transformers.
+#+BEGIN_SRC diff
+-type Builder = StateT Text IO
++type Builder = StateT Text (ReaderT Language IO)
+As you may have already understood, I wasn't using the “raw” ~State~ Monad, but
+rather the transformer version ~StateT~. The underlying Monad was ~IO~, because
+I needed to be able to read some files from the filesystem. By replacing ~IO~ by
+~ReaderT Language IO~, I basically fixed my “carry the variable to the correct
+function call easily” problem.
+Retrieving the chosen language is as simple as:
+#+BEGIN_SRC haskell
+getLanguage :: Builder Language
+getLanguage = lift ask
+And that was basically it. The complete [[][commit]] can be found on Github.
+Now, my point is not that Monad Transformers are the ultimate beast we will have
+to tame once and then everything will be shiny and easy. There are a lot of
+other way to achieve what I did with my ~Builder~ stack. For instance, in an
+OO language, I probably would have to add a new class member to my ~Builder~
+class and I would have done basically the same thing.
+However, there is something I really like about this approach: the ~Builder~
+type definition gives you a lot of useful information already. Both the ~State~
+and ~Reader~ Monads have a well established semantics most Haskellers will
+understand in a glance. A bit of documentation won’t hurt, but I suspect it is
+not as necessary as one could expect. Moreover, the presence of the ~IO~ Monad
+tells everyone using the ~Builder~ Monad might cause I/O.