<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Thomas Letan's Blog - haskell</title>
    <link>https://soap.coffee/~lthms/tags/haskell.html</link>
    <description>Posts tagged "haskell"</description>
    <atom:link href="https://soap.coffee/~lthms/tags/haskell.xml" rel="self"
               type="application/rss+xml" />
    
    
    <item>
      <title>Extensible Type-Safe Error Handling in Haskell</title>
      <link>https://soap.coffee/~lthms/posts/ExtensibleTypeSafeErrorHandling.html</link>
      <guid>https://soap.coffee/~lthms/posts/ExtensibleTypeSafeErrorHandling.html</guid>
      <pubDate>February 4, 2018</pubDate>
      <description>
        
        &lt;h1&gt;Extensible Type-Safe Error Handling in Haskell&lt;/h1&gt;&lt;div id=&quot;tags-list&quot;&gt;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#tag&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&amp;nbsp;&lt;a href=&quot;/~lthms/tags/haskell.html&quot; class=&quot;tag hover-coral&quot; marked=&quot;&quot;&gt;haskell&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;A colleague of mine introduced me to the benefits of
&lt;a href=&quot;https://crates.io/crates/error-chain&quot; class=&quot;hover-sky&quot; marked=&quot;&quot;&gt;&lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt;&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;, a crate which aims to
implement “&lt;em&gt;consistent error handling&lt;/em&gt;” for Rust. I found the overall design
pretty convincing, and in his use case, the crate really makes error handling
clearer and flexible. I knew &lt;a href=&quot;https://pijul.org&quot; class=&quot;hover-periwinkle&quot; marked=&quot;&quot;&gt;Pijul&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt; was also using
&lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt; at that time, but I never had the opportunity to dig more into it.&lt;/p&gt;
&lt;p&gt;At the same time, I have read quite a lot about &lt;em&gt;extensible effects&lt;/em&gt; in
Functional Programming, for an academic article I have submitted to &lt;a href=&quot;http://www.fm2018.org&quot; class=&quot;hover-lavender&quot; marked=&quot;&quot;&gt;Formal
Methods 2018&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;&lt;label for=&quot;fn1&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn1&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-right sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;The odds were in my favor: the aforementioned academic article has
been accepted. &lt;/span&gt;
&lt;/span&gt;. In particular, the
&lt;a href=&quot;https://hackage.haskell.org/package/freer&quot; class=&quot;hover-peach&quot; marked=&quot;&quot;&gt;freer&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt; package provides a very nice
API to define monadic functions which may use well-identified effects. For
instance, we can imagine that &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Console&lt;/span&gt;&lt;/code&gt; identifies the functions
which may print to and read from the standard output. A function
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;askPassword&lt;/span&gt;&lt;/code&gt; which displays a prompt and get the user password would
have this type signature:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;askPassword&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Console&lt;/span&gt; r =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt; r ()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compared to &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt;, &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt; allows for meaningful type
signatures. It becomes easier to reason about function composition, and you
know that a given function which lacks a given effect in its type signature
will not be able to use them. As a predictable drawback, &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt; can
become burdensome to use.&lt;/p&gt;
&lt;p&gt;Basically, when my colleague showed me his Rust project and how he was using
&lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt;, the question popped out. &lt;em&gt;Can we use an approach similar to
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt; to implement a Haskell-flavored &lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Spoiler alert: the answer is yes. In this post, I will dive into the resulting
API, leaving for another time the details of the underlying implementation&lt;label for=&quot;fn2&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn2&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-left sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;For once, I wanted to write about the &lt;em&gt;result&lt;/em&gt; of a project, instead of
&lt;em&gt;how it is implemented&lt;/em&gt;. &lt;/span&gt;
&lt;/span&gt;.
Believe me, there is plenty to say. If you want to have a look already, the
current implementation can be found on
&lt;a href=&quot;https://github.com/lthms/chain&quot; class=&quot;hover-coral&quot; marked=&quot;&quot;&gt;GitHub&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#github&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this article, I will use several “advanced” GHC pragmas. I will not explain
each of them, but I will &lt;em&gt;try&lt;/em&gt; to give some pointers for the reader who wants
to learn more.&lt;/p&gt;
&lt;h2&gt;State of the Art&lt;/h2&gt;
&lt;p&gt;This is not an academic publication, and my goal was primarily to explore the
arcane of the Haskell type system, so I might have skipped the proper study of
the state of the art. That being said, I have written programs in Rust and
Haskell before.&lt;/p&gt;
&lt;h3&gt;Starting Point&lt;/h3&gt;
&lt;p&gt;In Rust, &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt;&amp;lt;T, E&amp;gt;&lt;/code&gt; is the counterpart of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;T&lt;/span&gt;&lt;/code&gt; in
Haskell&lt;label for=&quot;fn3&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn3&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-right sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;I wonder if they deliberately choose to swap the two type arguments. &lt;/span&gt;
&lt;/span&gt;. You can use it to model to wrap either the result of a
function (&lt;code class=&quot;hljs&quot;&gt;T&lt;/code&gt;) or an error encountered during this computation (~E~). Both
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt;&lt;/code&gt; are used in order to achieve the same
end, that is writing functions which might fail.&lt;/p&gt;
&lt;p&gt;On the one hand, &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;E&lt;/span&gt;&lt;/code&gt; is a monad. It works exactly as
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Maybe&lt;/span&gt;&lt;/code&gt; (returning an error acts as a shortcut for the rest of the
function), but gives you the ability to specify &lt;em&gt;why&lt;/em&gt; the function has failed.
To deal with effects, the &lt;code class=&quot;hljs&quot;&gt;mtl&lt;/code&gt; package provides &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;EitherT&lt;/span&gt;&lt;/code&gt;, a
transformer version of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt;&lt;/code&gt; to be used in a monad stack.&lt;/p&gt;
&lt;p&gt;On the other hand, the Rust language provides the &lt;code class=&quot;hljs language-rust&quot;&gt;?&lt;/code&gt; syntactic sugar,
to achieve the same thing. That is, both languages provide you the means to
write potentially failing functions without the need to care locally about
failure. If your function &lt;code class=&quot;hljs&quot;&gt;f&lt;/code&gt; uses a function &lt;code class=&quot;hljs&quot;&gt;g&lt;/code&gt; which might fail, and want to
fail yourself if &lt;code class=&quot;hljs&quot;&gt;f&lt;/code&gt; fails, it becomes trivial.&lt;/p&gt;
&lt;p&gt;Out of the box, neither &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;EitherT&lt;/span&gt;&lt;/code&gt; nor &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt;&lt;/code&gt; is extensible.
The functions must use the exact same &lt;code class=&quot;hljs&quot;&gt;E&lt;/code&gt;, or errors must be converted
manually.&lt;/p&gt;
&lt;h3&gt;Handling Errors in Rust&lt;/h3&gt;
&lt;p&gt;Rust and the &lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt; crate provide several means to overcome this
limitation. In particular, it has the &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;Into&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;From&lt;/span&gt;&lt;/code&gt; traits to
ease the conversion from one error to another. Among other things, the
&lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt; crate provides a macro to easily define a wrapper around many
errors types, basically your own and the one defined by the crates you are
using.&lt;/p&gt;
&lt;p&gt;I see several drawbacks to this approach. First, it is extensible if you take
the time to modify the wrapper type each time you want to consider a new error
type. Second, either you can either use one error type or every error
type.&lt;/p&gt;
&lt;p&gt;However, the &lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt; package provides a way to solve a very annoying
limitation of &lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Result&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Either&lt;/span&gt;&lt;/code&gt;. When you “catch” an
error, after a given function returns its result, it can be hard to determine
from where the error is coming from. Imagine you are parsing a very complicated
source file, and the error you get is &lt;code class=&quot;hljs language-rust&quot;&gt;SyntaxError&lt;/code&gt; with no additional
context. How would you feel?&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;hljs&quot;&gt;error-chain&lt;/code&gt; solves this by providing an API to construct a chain of errors,
rather than a single value.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-rust&quot;&gt;&lt;span class=&quot;hljs-title function_ invoke__&quot;&gt;my_function&lt;/span&gt;().&lt;span class=&quot;hljs-title function_ invoke__&quot;&gt;chain_err&lt;/span&gt;(|| &lt;span class=&quot;hljs-string&quot;&gt;&quot;a message with some context&quot;&lt;/span&gt;)?;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code class=&quot;hljs&quot;&gt;chain_err&lt;/code&gt; function makes it easier to replace a given error in its
context, leading to be able to write more meaningful error messages for
instance.&lt;/p&gt;
&lt;h2&gt;The &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; Monad&lt;/h2&gt;
&lt;p&gt;The &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; is an attempt to bring together the extensible power of
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt; and the chaining of errors of &lt;code class=&quot;hljs&quot;&gt;chain_err&lt;/code&gt;. I will admit that,
for the latter, the current implementation of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; is probably
less powerful, but to be honest I mostly cared about the “extensible” thing, so
it is not very surprising.&lt;/p&gt;
&lt;p&gt;This monad is an alternative to neither Monad Stacks a la mtl nor to the
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt; monad. In its current state, it aims to be a more powerful and
flexible version of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;EitherT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Parameters&lt;/h3&gt;
&lt;p&gt;As often in Haskell, the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; monad can be parameterized in
several ways.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg (&lt;span class=&quot;hljs-title&quot;&gt;err&lt;/span&gt; :: [*]) m a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;msg&lt;/span&gt;&lt;/code&gt; is the type of messages you can stack to provide more context
to error handling&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;err&lt;/span&gt;&lt;/code&gt; is a &lt;em&gt;row of errors&lt;/em&gt;&lt;label for=&quot;fn4&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn4&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-left sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;You might have noticed &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;err&lt;/span&gt;&lt;/code&gt; is of kind &lt;code class=&quot;hljs language-haskell&quot;&gt;[*]&lt;/code&gt;. To write such a thing,
you will need the
&lt;a href=&quot;https://www.schoolofhaskell.com/user/konn/prove-your-haskell-for-great-safety/dependent-types-in-haskell&quot; class=&quot;hover-sky&quot; marked=&quot;&quot;&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;DataKinds&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;
GHC pragmas. &lt;/span&gt;
&lt;/span&gt;, it basically describes the set of
errors you will eventually have to handle&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;&lt;/code&gt; is the underlying monad stack of your application, knowing that
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; is not intended to be stacked itself&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;&lt;/code&gt; is the expected type of the computation result&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;achieve&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;abort&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The two main monadic operations which comes with ~ResultT~ are ~achieve~ and
~abort~. The former allows for building the context, by stacking so-called
messages which describe what you want to do. The latter allows for bailing on a
computation and explaining why.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;achieve&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m)
        =&amp;gt; msg
        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a
        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;achieve&lt;/span&gt;&lt;/code&gt; should be used for &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;do&lt;/span&gt;&lt;/code&gt; blocks. You can use
&lt;code class=&quot;hljs language-haskell&quot;&gt;&amp;lt;?&amp;gt;&lt;/code&gt; to attach a contextual message to a given computation.&lt;/p&gt;
&lt;p&gt;The type signature of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;abort&lt;/span&gt;&lt;/code&gt; is also interesting, because it
introduces the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Contains&lt;/span&gt;&lt;/code&gt; typeclass (e.g., it is equivalent to
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Member&lt;/span&gt;&lt;/code&gt; for &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Eff&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;abort&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Contains&lt;/span&gt; err e, &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m)
      =&amp;gt; e
      -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This reads as follows: “&lt;em&gt;you can abort with an error of type &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;&lt;/code&gt; if
and only if the row of errors &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;err&lt;/span&gt;&lt;/code&gt; contains the type
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt;&lt;/code&gt;.&lt;/em&gt;”&lt;/p&gt;
&lt;p&gt;For instance, imagine we have an error type &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;FileError&lt;/span&gt;&lt;/code&gt; to describe
filesystem-related errors. Then, we can imagine the following function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;readContent&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Contains&lt;/span&gt; err &lt;span class=&quot;hljs-type&quot;&gt;FileError&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
            =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt;
            -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could leverage this function in a given project, for instance, to read its
configuration files (for the sake of the example, it has several configuration
files). This function can use its own type to describe ill-formed description
(&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ConfigurationError&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;parseConfiguration&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;Contains&lt;/span&gt; err &lt;span class=&quot;hljs-type&quot;&gt;ConfigurationError&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
                   =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
                   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt;
                   -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m &lt;span class=&quot;hljs-type&quot;&gt;Configuration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To avoid repeating &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Contains&lt;/span&gt;&lt;/code&gt; when the row of errors needs to
contains several elements, we introduce &lt;code class=&quot;hljs language-haskell&quot;&gt;:&amp;lt;&lt;/code&gt;&lt;label for=&quot;fn5&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn5&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-right sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;If you are confused by &lt;code class=&quot;hljs language-haskell&quot;&gt;:&amp;lt;&lt;/code&gt;, it is probably because you were
not aware that the
&lt;a href=&quot;https://ocharles.org.uk/blog/posts/2014-12-08-type-operators.html&quot; class=&quot;hover-rose&quot; marked=&quot;&quot;&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;TypeOperators&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;
GHC pragma was a thing. &lt;/span&gt;
&lt;/span&gt; (read &lt;em&gt;subset or
equal&lt;/em&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;getConfig&lt;/span&gt; :: ( &apos;[&lt;span class=&quot;hljs-type&quot;&gt;FileError&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;ConfigurationError&lt;/span&gt;] :&amp;lt; err
             , &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
             =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; err m &lt;span class=&quot;hljs-type&quot;&gt;Configuration&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;getConfig&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
  achieve &lt;span class=&quot;hljs-string&quot;&gt;&quot;get configuration from ~/.myapp directory&quot;&lt;/span&gt; $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    f1 &amp;lt;- readContent &lt;span class=&quot;hljs-string&quot;&gt;&quot;~/.myapp/init.conf&quot;&lt;/span&gt;
              &amp;lt;?&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fetch the main configuration&quot;&lt;/span&gt;
    f2 &amp;lt;- readContent &lt;span class=&quot;hljs-string&quot;&gt;&quot;~/.myapp/net.conf&quot;&lt;/span&gt;
              &amp;lt;?&amp;gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fetch the net-related configuration&quot;&lt;/span&gt;

    parseConfiguration f1 f2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might see, now, why I say ~ResultT~ is extensible. You can use two functions
with totally unrelated errors, as long as the caller advertises that with
~Contains~ or ~:&amp;lt;~.&lt;/p&gt;
&lt;h3&gt;Recovering by Handling Errors&lt;/h3&gt;
&lt;p&gt;Monads are traps, you can only escape them by playing with their
rules. &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; comes with &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runResultT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runResultT&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg &apos;[] m a -&amp;gt; m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might be surprising: we can only escape out from the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt;
if we do not use &lt;em&gt;any errors at all&lt;/em&gt;. That is, &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; forces us to
handle errors before calling &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runResultT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; provides several functions prefixed by &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recover&lt;/span&gt;&lt;/code&gt;.
Their type signatures can be a little confusing, so we will dive into the
simpler one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recover&lt;/span&gt; :: &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; e m msg err a.
           (&lt;span class=&quot;hljs-type&quot;&gt;Monad&lt;/span&gt; m)
        =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg (e &apos;: err) m a
        -&amp;gt; (e -&amp;gt; [msg] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a)
        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recover&lt;/span&gt;&lt;/code&gt; allows for &lt;em&gt;removing&lt;/em&gt; an error type from the row of errors,
To do that, it requires to provide an error handler to determine what to do
with the error raised during the computation and the stack of messages at that
time. Using &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recover&lt;/span&gt;&lt;/code&gt;, a function may use more errors than advertised
in its type signature, but we know by construction that in such a case, it
handles these errors so that it is transparent for the function user. The type
of the handler is &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;e&lt;/span&gt; -&amp;gt; [msg] -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m a&lt;/code&gt;, which means
the handler &lt;em&gt;can raise errors if required&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recoverWhile&lt;/span&gt; msg&lt;/code&gt; is basically a synonym for &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;achieve&lt;/span&gt; msg $ recover&lt;/code&gt;. &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recoverMany&lt;/span&gt;&lt;/code&gt; allows for doing the same with a
row of errors, by providing as many functions as required. Finally,
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recoverManyWith&lt;/span&gt;&lt;/code&gt; simplifies &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recoverMany&lt;/span&gt;&lt;/code&gt;: you can provide
only one function tied to a given typeclass, on the condition that the handling
errors implement this typeclass.&lt;/p&gt;
&lt;p&gt;Using &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recover&lt;/span&gt;&lt;/code&gt; and its siblings often require to help a bit the
Haskell type system, especially if we use lambdas to define the error handlers.
Doing that is usually achieved with the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Proxy&lt;/span&gt; a&lt;/code&gt; dataype (where
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;a&lt;/span&gt;&lt;/code&gt; is a phantom type). I would rather use the
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;TypeApplications&lt;/span&gt;&lt;/code&gt; pragma&lt;label for=&quot;fn6&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn6&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-left sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;The
&lt;a href=&quot;https://medium.com/@zyxoas/abusing-haskell-dependent-types-to-make-redis-queues-safer-cc31db943b6c&quot; class=&quot;hover-mint&quot; marked=&quot;&quot;&gt;TypeApplications&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;
pragmas is probably one of my favorites.&lt;/span&gt;
&lt;span class=&quot;footnote-p&quot;&gt;When I use it, it feels almost like if I were writing a Coq document. &lt;/span&gt;
&lt;/span&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;recoverManyWith&lt;/span&gt; @[&lt;span class=&quot;hljs-type&quot;&gt;FileError&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;NetworkError&lt;/span&gt;] @&lt;span class=&quot;hljs-type&quot;&gt;DescriptiveError&lt;/span&gt;
    (&lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; x &amp;lt;- readFromFile f
        y &amp;lt;- readFromNetwork socket
        printToStd x y)
    printErrorAndStack
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;DecriptiveError&lt;/span&gt;&lt;/code&gt; typeclass can be seen as a dedicated
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Show&lt;/span&gt;&lt;/code&gt;, to give textual representation of errors. It is inspired by
the macros of &lt;code class=&quot;hljs&quot;&gt;error_chain&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can start from an empty row of errors, and allows ourselves to
use more errors thanks to the &lt;code class=&quot;hljs&quot;&gt;recover*&lt;/code&gt; functions.&lt;/p&gt;
&lt;h2&gt;&lt;code class=&quot;hljs&quot;&gt;cat&lt;/code&gt; in Haskell using &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; only cares about error handling. The rest of the work is up
to the underlying monad &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;m&lt;/span&gt;&lt;/code&gt;. That being said, nothing forbids us to
provide fine-grained API, &lt;em&gt;e.g.&lt;/em&gt;, for Filesystem-related functions. From an
error handling perspective, the functions provided by &lt;code class=&quot;hljs&quot;&gt;Prelude&lt;/code&gt; (the standard
library of Haskell) are pretty poor, and the documentation is not really
precise regarding the kind of error we can encounter while using it.&lt;/p&gt;
&lt;p&gt;In this section, I will show you how we can leverage &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; to
&lt;strong&gt;(i)&lt;/strong&gt; define an error-centric API for basic file management functions and
&lt;strong&gt;(ii)&lt;/strong&gt; use this API to implement a &lt;code class=&quot;hljs&quot;&gt;cat&lt;/code&gt;-like program which read a file and
print its content in the standard output.&lt;/p&gt;
&lt;h3&gt;(A Lot Of) Error Types&lt;/h3&gt;
&lt;p&gt;We could have one sum type to describe in the same place all the errors we can
find, and later use the pattern matching feature of Haskell to determine which
one has been raised. The thing is, this is already the job done by the row of
errors of ~ResultT~. Besides, this means that we could raise an error for being
not able to write something into a file in a function which /opens/ a file.&lt;/p&gt;
&lt;p&gt;Because ~ResultT~ is intended to be extensible, we should rather define several
types, so we can have a fine-grained row of errors. Of course, too many types
will become burdensome, so this is yet another time where we need to find the
right balance.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AlreadyInUse&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;AlreadyInUse&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;newtype&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;DoesNotExist&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;DoesNotExist&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;AccessDeny&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;AccessDeny&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;IOMode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;EoF&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;EoF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IllegalOperation&lt;/span&gt; = &lt;span class=&quot;hljs-type&quot;&gt;IllegalRead&lt;/span&gt; | &lt;span class=&quot;hljs-type&quot;&gt;IllegalWrite&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To be honest, this is a bit too much for the real life, but we are in a blog post
here, so we should embrace the potential of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Filesystem API&lt;/h3&gt;
&lt;p&gt;By reading the
&lt;a href=&quot;https://hackage.haskell.org/package/base-4.9.1.0/docs/System-IO.html&quot; class=&quot;hover-coral&quot; marked=&quot;&quot;&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;System&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt;&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;
documentation, we can infer what our functions type signatures should look
like. I will not discuss their actual implementation in this article, as this
requires me to explain how &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt; deals with errors itself (and this
article is already long enough to my taste). You can have a look at &lt;a href=&quot;https://gist.github.com/lthms/c669e68e284a056dc8c0c3546b4efe56&quot; class=&quot;hover-peach&quot; marked=&quot;&quot;&gt;this
gist&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt; if you
are interested.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;openFile&lt;/span&gt; :: ( &apos;[&lt;span class=&quot;hljs-type&quot;&gt;AlreadyInUse&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;DoesNotExist&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;AccessDeny&lt;/span&gt;] :&amp;lt; err
            , &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
         =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IOMode&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m &lt;span class=&quot;hljs-type&quot;&gt;Handle&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;getLine&lt;/span&gt; :: (&apos;[&lt;span class=&quot;hljs-type&quot;&gt;IllegalOperation&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;EoF&lt;/span&gt;] :&amp;lt; err, &lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
        =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Handle&lt;/span&gt;
        -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m &lt;span class=&quot;hljs-type&quot;&gt;Text&lt;/span&gt;

&lt;span class=&quot;hljs-title&quot;&gt;closeFile&lt;/span&gt; :: (&lt;span class=&quot;hljs-type&quot;&gt;MonadIO&lt;/span&gt; m)
          =&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;Handle&lt;/span&gt;
          -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; msg err m ()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Implementing &lt;code class=&quot;hljs&quot;&gt;cat&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We can use the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; monad, its monadic operations and our
functions to deal with the file system in order to implement a &lt;code class=&quot;hljs&quot;&gt;cat&lt;/code&gt;-like
program. I tried to comment on the implementation to make it easier to follow.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cat&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;FilePath&lt;/span&gt; -&amp;gt; &lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;String&lt;/span&gt; err &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt; ()
&lt;span class=&quot;hljs-title&quot;&gt;cat&lt;/span&gt; path =
  &lt;span class=&quot;hljs-comment&quot;&gt;-- We will try to open and read this file to mimic&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- `cat` behaviour.&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- We advertise that in case something goes wrong&lt;/span&gt;
  &lt;span class=&quot;hljs-comment&quot;&gt;-- the process.&lt;/span&gt;
  achieve (&lt;span class=&quot;hljs-string&quot;&gt;&quot;cat &quot;&lt;/span&gt; ++ path) $ &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;-- We will recover from a potential error,&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;-- but we will abstract away the error using&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;-- the `DescriptiveError` typeclass. This way,&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;-- we do not need to give one handler by error&lt;/span&gt;
    &lt;span class=&quot;hljs-comment&quot;&gt;-- type.&lt;/span&gt;
    recoverManyWith @[&lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;AlreadyInUse&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;DoesNotExist&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;AccessDeny&lt;/span&gt;, &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;IllegalOperation&lt;/span&gt;]
                    @(&lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;DescriptiveError&lt;/span&gt;)
      (&lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt; f &amp;lt;- &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.openFile path &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;ReadMode&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- `repeatUntil` works like `recover`, except&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- it repeats the computation until the error&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- actually happpens.&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- I could not have used `getLine` without&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- `repeatUntil` or `recover`, as it is not&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- in the row of errors allowed by&lt;/span&gt;
          &lt;span class=&quot;hljs-comment&quot;&gt;-- `recoverManyWith`.&lt;/span&gt;
          repeatUntil @(&lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.&lt;span class=&quot;hljs-type&quot;&gt;EoF&lt;/span&gt;)
              (&lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.getLine f &amp;gt;&amp;gt;= liftIO . print)
              (\_ _ -&amp;gt; liftIO $ putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;%EOF&quot;&lt;/span&gt;)
          closeFile f)
      printErrorAndStack
    &lt;span class=&quot;hljs-keyword&quot;&gt;where&lt;/span&gt;
      &lt;span class=&quot;hljs-comment&quot;&gt;-- Using the `DescriptiveError` typeclass, we&lt;/span&gt;
      &lt;span class=&quot;hljs-comment&quot;&gt;-- can print both the stack of Strings which form&lt;/span&gt;
      &lt;span class=&quot;hljs-comment&quot;&gt;-- the context, and the description of the generic&lt;/span&gt;
      &lt;span class=&quot;hljs-comment&quot;&gt;-- error.&lt;/span&gt;
      printErrorAndStack e ctx = &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;
        liftIO . putStrLn $ &lt;span class=&quot;hljs-type&quot;&gt;Fs&lt;/span&gt;.describe e
        liftIO $ putStrLn &lt;span class=&quot;hljs-string&quot;&gt;&quot;stack:&quot;&lt;/span&gt;
        liftIO $ print ctx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The type signature of &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;cat&lt;/span&gt;&lt;/code&gt; teaches us that this function handles any
error it might encounter. This means we can use it anywhere we want: both in
another computation inside &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; which might raise errors
completely unrelated to the file system, or we can use it with
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;runResultT&lt;/span&gt;&lt;/code&gt;, escaping the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ResultT&lt;/span&gt;&lt;/code&gt; monad (only to fall
into the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt; monad, but this is another story).&lt;/p&gt;
        
      </description>
    </item>
    
    
    
    <item>
      <title>Monad Transformers are a Great Abstraction</title>
      <link>https://soap.coffee/~lthms/posts/MonadTransformers.html</link>
      <guid>https://soap.coffee/~lthms/posts/MonadTransformers.html</guid>
      <pubDate>July 15, 2017</pubDate>
      <description>
        
        &lt;h1&gt;Monad Transformers are a Great Abstraction&lt;/h1&gt;&lt;div id=&quot;tags-list&quot;&gt;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#tag&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&amp;nbsp;&lt;a href=&quot;/~lthms/tags/haskell.html&quot; class=&quot;tag hover-mint&quot; marked=&quot;&quot;&gt;haskell&lt;/a&gt; &lt;/div&gt;
&lt;div class=&quot;markdown-alert markdown-alert-caution&quot;&gt;&lt;p class=&quot;markdown-alert-title&quot;&gt;&lt;svg class=&quot;octicon octicon-stop mr-2&quot; viewbox=&quot;0 0 16 16&quot; version=&quot;1.1&quot; width=&quot;16&quot; height=&quot;16&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;Caution&lt;/p&gt;&lt;p&gt;Time has passed since the publication of this article. Whether or not I agree
with its conclusions is an open question. Monad Transformers are a great
abstraction, but nowadays I would most certainly choose another approach.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;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 &lt;em&gt;the&lt;/em&gt; Monad. It is even the contrary. When someone asks me how I would
define Monads in only a few words, I say monads are a convenient formalism to
chain specific computations. Once I’ve got that, I started noticing “monadic
construction” everywhere, from the Rust &lt;code class=&quot;hljs language-rust&quot;&gt;?&lt;/code&gt; operator to the &lt;a href=&quot;https://blog.drewolson.org/elixirs-secret-weapon/&quot; class=&quot;hover-coral&quot; marked=&quot;&quot;&gt;Elixir
&lt;code class=&quot;hljs language-elixir&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;with&lt;/span&gt;&lt;/code&gt; keyword&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Haskell often uses another concept above Monads: Monad Transformers. This allows
you to work not only with &lt;em&gt;one&lt;/em&gt; 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 the answer.&lt;/p&gt;
&lt;p&gt;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 written a
software called &lt;code class=&quot;hljs&quot;&gt;celtchar&lt;/code&gt; to build a novel from a list of files. One of its
newest features 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
calls.&lt;/p&gt;
&lt;p&gt;In Haskell, you deal with that kind of challenge 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.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-diff&quot;&gt;&lt;span class=&quot;hljs-deletion&quot;&gt;-type Builder = StateT Text IO&lt;/span&gt;
&lt;span class=&quot;hljs-addition&quot;&gt;+type Builder = StateT Text (ReaderT Language IO)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you may have already understood, I wasn&apos;t using the “raw” &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt;&lt;/code&gt;
Monad, but rather the transformer version &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;StateT&lt;/span&gt;&lt;/code&gt;. The underlying
Monad was &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt;, because I needed to be able to read some files from
the file system. By replacing &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt; by &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;ReaderT&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Language&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt;,
I basically fixed my “carry the variable to the correct function call easily”
problem.&lt;/p&gt;
&lt;p&gt;Retrieving the chosen language is as simple as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-title&quot;&gt;getLanguage&lt;/span&gt; :: &lt;span class=&quot;hljs-type&quot;&gt;Builder&lt;/span&gt; &lt;span class=&quot;hljs-type&quot;&gt;Language&lt;/span&gt;
&lt;span class=&quot;hljs-title&quot;&gt;getLanguage&lt;/span&gt; = lift ask
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And that was basically it.&lt;/p&gt;
&lt;p&gt;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&lt;label for=&quot;fn1&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn1&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-right sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;It is amusing to see Past Me being careful here. &lt;/span&gt;
&lt;/span&gt;. There are a lot of
other ways to achieve what I did with my &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Builder&lt;/span&gt;&lt;/code&gt; stack. For instance, in an
OO language, I probably would have to add a new class member to my &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Builder&lt;/span&gt;&lt;/code&gt;
class and I would have done basically the same thing.&lt;/p&gt;
&lt;p&gt;However, there is something I really like about this approach: the
&lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Builder&lt;/span&gt;&lt;/code&gt; type definition gives you a lot of useful information
already. Both the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;State&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Reader&lt;/span&gt;&lt;/code&gt; 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 &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;IO&lt;/span&gt;&lt;/code&gt; Monad tells everyone using
the &lt;code class=&quot;hljs language-haskell&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;Builder&lt;/span&gt;&lt;/code&gt; Monad might cause I/O.&lt;/p&gt;
        
      </description>
    </item>
    
    
  </channel>
</rss>
