Investigating the I/O Monad in Go
<p>In this article, we will continue <a href="https://betterprogramming.pub/investigate-functional-programming-concepts-in-go-1dada09bc913" rel="noopener ugc nofollow" target="_blank">our investigation</a> of applying functional programming concepts to <a href="https://go.dev/" rel="noopener ugc nofollow" target="_blank">Go</a>. While in the previous article, we concentrated on <a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener ugc nofollow" target="_blank">pure</a> functions, we will dive into the ideas and implementation behind <a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">effectful </a>functions.</p>
<h1>Guiding Principles</h1>
<p>Let’s recap some of the guiding principles.</p>
<h2>Pure functions</h2>
<p>In functional programming, we try to isolate <a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener ugc nofollow" target="_blank">pure</a> functions from <a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">effectful </a>functions. Functions are considered pure if the output of a function depends on its inputs only and if the invocation of such a function does not change anything outside the scope of the function itself (e.g., global variables, the console, files, etc.).</p>
<h2>Immutability</h2>
<p>Data structures are considered immutable, i.e., instead of modifying a structure to change data, we create copies of that structure and apply the modifications to that copy.</p>
<p>There exist many benefits of immutability, including:</p>
<ul>
<li>The caller of a function does not have to worry that the function modifies its input data, so it’s safe to pass the same input to multiple functions, synchronously or asynchronously, to cache it, etc.</li>
<li>Functions are easy to understand since, by definition, it is clear that inputs are always read-only and that the only output of a function is its return value. That makes these functions easy to reason about and easy to test</li>
</ul>
<h2>Composition</h2>
<p>When designing functions, we attempt to design them so the output of one function can be passed as an input to the next function, forming a new function.</p>
<p>If all functions in a composition are pure, then the result of the composition is pure, too, so we can derive more complex scenarios from simpler ones.</p>
<h1>Side Effects</h1>
<p>While it is desirable to work with pure functions, most real-world programs need <a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">side effects</a> because they, e.g., read files, consume user input, rely on environment variables, make HTTP requests, etc.</p>
<p>Side effects are operations that alter or rely on a state outside the current function's scope. Here’s some examples:</p>
<ul>
<li>Reading from a file because the file’s content lies outside of the control of the function. So executing a function repeatedly does not guarantee to produce the same result each time</li>
<li>Reading an environment variable</li>
<li>Writing to a file because the write operation might fail</li>
<li>Writing to the console because doing this repeatedly will produce different results (one vs many console logs)</li>
<li>Relying on the current time</li>
</ul>
<p>In functional programming, we try to isolate side effects from pure functions such that their execution is effectful but their composition remains pure.</p>
<h2>Representation</h2>
<p>We represent a side effect as a function without inputs but with a strongly typed return value.</p>
<p><a href="https://betterprogramming.pub/investigating-the-i-o-monad-in-go-3c0fabbb4b3d">Visit Now</a></p>