Investigating the I/O Monad in Go

<p>In this article, we will continue&nbsp;<a href="https://betterprogramming.pub/investigate-functional-programming-concepts-in-go-1dada09bc913" rel="noopener ugc nofollow" target="_blank">our investigation</a>&nbsp;of applying functional programming concepts to&nbsp;<a href="https://go.dev/" rel="noopener ugc nofollow" target="_blank">Go</a>. While in the previous article, we concentrated on&nbsp;<a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener ugc nofollow" target="_blank">pure</a>&nbsp;functions, we will dive into the ideas and implementation behind&nbsp;<a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">effectful&nbsp;</a>functions.</p> <h1>Guiding Principles</h1> <p>Let&rsquo;s recap some of the guiding principles.</p> <h2>Pure functions</h2> <p>In functional programming, we try to isolate&nbsp;<a href="https://en.wikipedia.org/wiki/Pure_function" rel="noopener ugc nofollow" target="_blank">pure</a>&nbsp;functions from&nbsp;<a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">effectful&nbsp;</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&rsquo;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&nbsp;<a href="https://en.wikipedia.org/wiki/Side_effect_(computer_science)" rel="noopener ugc nofollow" target="_blank">side effects</a>&nbsp;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&#39;s scope. Here&rsquo;s some examples:</p> <ul> <li>Reading from a file because the file&rsquo;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>