<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Paul Louth]]></title><description><![CDATA[Notes from a Small Functional Island]]></description><link>https://paullouth.com/</link><image><url>https://paullouth.com/favicon.png</url><title>Paul Louth</title><link>https://paullouth.com/</link></image><generator>Ghost 5.88</generator><lastBuildDate>Wed, 22 Apr 2026 04:55:39 GMT</lastBuildDate><atom:link href="https://paullouth.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 12- WriterT monad transformer]]]></title><description><![CDATA[The WriterT monad transformer allows for aggregating output using pure expressions. ]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-12-writert-monad-transformer/</link><guid isPermaLink="false">670b898aeb84da82ea6018df</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[functor]]></category><category><![CDATA[monad]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[traits]]></category><category><![CDATA[monoid]]></category><category><![CDATA[hkt]]></category><category><![CDATA[applicatives]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Sun, 13 Oct 2024 10:29:13 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/10/writert.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/10/writert.png" alt="Higher Kinds in C# with language-ext [Part 12- WriterT monad transformer]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow along &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/">Part 8 - Monads (continued)</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-9-monad-transformers/">Part 9 - Monad Transformers</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-10-readert-monad-transformer/">Part 10 - ReaderT monad transformer</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-11-statet-monad-transformer/">Part 11 - StateT monad transformer</a></li></ul><p>In the last article we covered the <a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-11-statet-monad-transformer/"><code>StateT</code> monad-transformer</a>, which is a close relative to the <a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-10-readert-monad-transformer/"><code>ReaderT</code> monad-transformer</a> from the article before that.  The <code>WriterT</code> monad-transformer is implemented in exactly the same way as the <code>StateT</code> monad-transformer.  The only difference is that the state type (<code>S</code> in the <code>StateT</code> transformer, renamed to <code>W</code> in the <code>WriterT</code>) is constrained to be a <code>Monoid&lt;W&gt;</code>.  </p><p>That means we can create an &apos;empty&apos; <code>W</code> and we can &apos;append&apos;/&apos;combine&apos; values to <code>W</code>.  So, <code>WriterT</code> is good for logging multiple outputs, or aggregating an output value over the course of a monadic expression.</p><p>The classic way to implement a <code>Writer</code> monad (not transformer), is like so:</p><pre><code class="language-csharp">public record Writer&lt;W, A&gt;(Func&lt;(W Output, A Value)&gt; runWriter)
    where W : Monoid&lt;W&gt;
{
    public Writer&lt;W, B&gt; Bind&lt;B&gt;(Func&lt;A, Writer&lt;W, B&gt;&gt; f) =&gt;
        new (() =&gt;
        {
            var (output1, value1) = runWriter();
            var (output2, value2) = f(value1).runWriter();
            return (output1.Combine(output2), value2);
        });
}</code></pre><blockquote>This example is not using traits, just so I can show you just the raw components of a <code>Writer</code> monad</blockquote><p>The interesting thing here is that the <code>runWriter</code> property doesn&apos;t have an input state as part of its <code>Func</code> delegate.  It simply combines the outputs of two invocations of <code>runWriter</code> in the <code>Bind</code> method (<code>output1.Combine(output2)</code>).  </p><p>That allows for a very simple <code>tell</code> function that we use to aggregate our output:</p><pre><code class="language-csharp">public static class Writer
{
    public static Writer&lt;W, Unit&gt; tell&lt;W&gt;(W output)
        where W : Monoid&lt;W&gt; =&gt;
        new (() =&gt; (output, unit));
}</code></pre><p>We simply return the <code>output</code> value as-is, without doing any extra processing. We can then use that to log individual elements to the monoidal output-state:</p><pre><code class="language-csharp">static Writer&lt;Seq&lt;string&gt;, Unit&gt; example =&gt;
  from _1 in tell(Seq(&quot;Hello&quot;))
  from _2 in tell(Seq(&quot;World&quot;))
  select unit;</code></pre><p>The problem with this approach is that we call <code>tell</code> much less than we call <code>Bind</code>.  And in the <code>Bind</code> function we call <code>Monoid.Combine</code> <em>every single time</em>.  This is problematic for two reasons:</p><ul><li>Most of the time the outputs will be empty, so this is wasted work</li><li>When they&apos;re not empty, the outputs could need to perform significant work to <code>Combine</code> the two states.<ul><li>Imagine concatenating two (immutable) linked-lists that are 100 items long each, that would require a 100 item loop to build a new list!  You can easily get into a problem of <em>exponential</em> monoidal combines.</li></ul></li></ul><p>So, to get around this, we want to remove the <code>Combine</code> from the <code>Bind</code> function and find another way to aggregate the output.  Really, we want the work to happen in the <code>tell</code> function, because that is explicitly doing the work of outputting data.</p><p>To achieve this, we must first update the <code>Func&lt;(W Output, A Value)&gt; runWriter</code> to take a <code>W</code> input:</p><pre><code class="language-csharp">Func&lt;W, (W Output, A Value)&gt; runWriter</code></pre><p>Then update our <code>Bind</code> function to remove the <code>Monoid.Combine</code> and to pass the initial <code>output0</code> value through the expression:</p><pre><code class="language-csharp">public Writer&lt;W, B&gt; Bind&lt;B&gt;(Func&lt;A, Writer&lt;W, B&gt;&gt; f) =&gt;
    new (output0 =&gt;
    {
        var (output1, value1) = runWriter(output0);
        var (output2, value2) = f(value1).runWriter(output1);
        return (output2, value2);
    });
</code></pre><blockquote>The eagle-eyed among you will realise that this is exactly the same as the <code>State</code> monad.  It threads a state through the computation, returning the updated value.</blockquote><p>Now we can update the <code>tell</code> function:</p><pre><code class="language-csharp"> public static Writer&lt;W, Unit&gt; tell&lt;W&gt;(W value)
      where W : Monoid&lt;W&gt; =&gt;
      new (output =&gt; (output.Combine(value), unit));</code></pre><p>Most of the time when using <code>Writer</code> our output is a collection of some flavour.  And so, this <code>tell</code> function, usually, is just appending or consing a single item to the collection.  And so, the risk of exponential concatenation issues goes away (as long as the monoid is implemented efficiently, something to take care with).  This is much more efficient, generally.</p><p>The thing is, if we look at the implementation of <code>Writer</code>, we can now drop the <code>Monoid&lt;W&gt;</code> constraint:</p><pre><code class="language-csharp">public record Writer&lt;W, A&gt;(Func&lt;W, (W Output, A Value)&gt; runWriter)
{
    public Writer&lt;W, B&gt; Bind&lt;B&gt;(Func&lt;A, Writer&lt;W, B&gt;&gt; f) =&gt;
        new (output0 =&gt;
        {
            var (output1, value1) = runWriter(output0);
            var (output2, value2) = f(value1).runWriter(output1);
            return (output2, value2);
        });
}</code></pre><p>We only need it for the <code>tell</code> function.  The rest of the implementation is exactly the same as <code>State</code>.  So, we don&apos;t actually need to implement <code>WriterT</code>.  We can simply write a <code>tell</code> function for <code>StateT</code>:</p><pre><code class="language-csharp">public static StateT&lt;W, M, Unit&gt; tell&lt;M, W&gt;(W value)
    where W : Monoid&lt;W&gt;
    where M : Monad&lt;M&gt; =&gt;
    StateT.modify&lt;M, W&gt;(output =&gt; output.Combine(value));</code></pre><p>Or even, generalise it over all <code>Stateful</code> types:</p><pre><code class="language-csharp">public static K&lt;M, Unit&gt; tell&lt;M, W&gt;(W value)
    where W : Monoid&lt;W&gt;
    where M : Stateful&lt;M, W&gt; =&gt;
    Stateful.modify&lt;M, W&gt;(output =&gt; output.Combine(value));</code></pre><p>That means <em>anything </em>that implements <code>Stateful&lt;M, W&gt;</code> can now aggregate an output state using the <code>Monoid&lt;W&gt;</code> trait.</p><p>So, why would we ever implement <code>WriterT</code> if <code>StateT</code> is good enough?  Well, I&apos;ve asked myself that question a few times.  I&apos;ve considered dropping the <code>Writer</code> and <code>WriterT</code> types altogether.  But, have decided to keep them because they are <em>declarative</em> &#x2013; they tell the reader of your code that you&apos;re aggregating an output, not merely carrying some state.  Communication with the reader of your code (including yourself) is important and this seems like a good distinction, even if &#x2013; at a fundamental level &#x2013; the types are the same.</p><p>What that does mean is that I can keep this episode short and say:</p><blockquote><em>&quot;<code>WriterT</code> is the same as <code>StateT</code>, we just have a <code>Monoid</code> constraint on the state&quot;.  So, if you grokked the last article, then you&apos;re all good.</em></blockquote><h2 id="rwst">RWST</h2><p>Now that we&apos;ve defined <code>ReaderT</code>, <code>WriterT</code>, and <code>StateT</code>, we can finally implement <code>RWST</code>:</p><pre><code class="language-csharp">public record RWST&lt;R, W, S, M, A&gt;(ReaderT&lt;R, WriterT&lt;W, StateT&lt;S, M&gt;&gt;, A&gt; runRWS) 
    : K&lt;RWST&lt;R, W, S, M&gt;, A&gt;
    where M : Monad&lt;M&gt;
    where W : Monoid&lt;W&gt;;</code></pre><p>Reader, Writer, State, Transformer.  This type is a combination of the <code>ReaderT</code> transformer, the <code>WriterT</code> transformer, the <code>StateT</code> transformer, and an <code>M</code> monad.  So, <strong>four</strong> stacked behaviours.  It is especially good for defining your &apos;application monad&apos;, i.e. the one that carries configuration, state, and needs to log as it goes, as well as being able to lift an <code>M</code> monad (<code>IO</code>, <code>Option</code>, etc.).</p><p>We will cover this in detail in the next article.  But if you want some homework, see if you can implement the <code>RWST</code> traits:</p><pre><code class="language-csharp">public class RWST&lt;R, W, S, M&gt; : 
    MonadT&lt;RWST&lt;R, W, S, M&gt;, M&gt;, 
    Readable&lt;RWST&lt;R, W, S, M&gt;, R&gt;,
    Writable&lt;RWST&lt;R, W, S, M&gt;, W&gt;,
    Stateful&lt;RWST&lt;R, W, S, M&gt;, S&gt;
    where M : Monad&lt;M&gt;
    where W : Monoid&lt;W&gt;
{
   // Implementation goes here!
}</code></pre><blockquote>Remember that all of the behaviours already exist in the wrapped types, you don&apos;t need to implement them yourself, you simply need to lift them into the wrapper-transformer.</blockquote><p><em>Until next time...</em></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 11- StateT monad transformer]]]></title><description><![CDATA[The StateT monad transformer allows for mutation of state using pure expressions. We dive into how it works.]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-11-statet-monad-transformer/</link><guid isPermaLink="false">66ab1d25eb84da82ea60139a</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[hkt]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[monad]]></category><category><![CDATA[traits]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Sat, 03 Aug 2024 11:23:32 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/08/statet.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/08/statet.png" alt="Higher Kinds in C# with language-ext [Part 11- StateT monad transformer]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow along &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/">Part 8 - Monads (continued)</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-9-monad-transformers/">Part 9 - Monad Transformers</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-10-readert-monad-transformer/">Part 10 - ReaderT monad transformer</a></li></ul><p>In the last article we went into quite some depth, covering the <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/Reader/ReaderT/ReaderT.cs?ref=paullouth.com"><code>ReaderT</code> monad-transformer</a> and the <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Readable/Readable.Trait.cs?ref=paullouth.com"><code>Readable</code> trait</a> (that provides access to an environment value from a structure), meaning we can generalise the idea of monads with environments.</p><p>In this article we&apos;ll cover a close relative of <code>ReaderT</code>, namely <code>StateT</code>.  Where <code>ReaderT</code> provides access to a fixed environment value, <code>StateT</code> allows the mutation of that value.</p><p>&quot;Mutation&quot;, you say?! Isn&apos;t that frowned upon in pure functional programming? Yes, it is, however <code>StateT</code> doesn&apos;t mutate a value in-place, it propagates modifications through the pure computation, giving us the best of both worlds.</p><blockquote>Because many of the concepts of <code>StateT</code> are similar to <code>ReaderT</code> I&apos;ll try to make this article a little more focused on the differences, rather than rehash everything from the last article.  By now you should know what traits are, monads, and monad-transformers.  We&apos;re going to implement another monad-transformer...</blockquote><p>You may remember that the core of the <code>ReaderT</code> implementation looks like this:</p><pre><code class="language-csharp">public record ReaderT&lt;Env, M, A&gt;(Func&lt;Env, K&lt;M, A&gt;&gt; runReader) : K&lt;ReaderT&lt;Env, M&gt;, A&gt;
    where M : Monad&lt;M&gt;
{
    public K&lt;M, A&gt; Run(Env env) =&gt; 
        this.runReader(env);   

   ...    
}</code></pre><p>The <code>runReader</code> function, that is its only property, takes an <code>Env</code> value, which is the environment that gets threaded through the <code>Bind</code> function:</p><pre><code class="language-csharp">public ReaderT&lt;Env, M, B&gt; Bind&lt;B&gt;(Func&lt;A, ReaderT&lt;Env, M, B&gt;&gt; f) =&gt;
    new(env =&gt; M.Bind(runReader(env), x =&gt; f(x).runReader(env)));</code></pre><blockquote>The reason, for looking at these again, is that with a few changes in these two functions, we will have a state-monad rather than a reader-monad. </blockquote><p>It should be fairly obvious from these declarations that the <code>ReaderT</code> can&apos;t modify its environment (and return the result).  That&apos;s because the <code>runReader</code> function doesn&apos;t have an <code>Env</code> in its return-type: <code>Func&lt;Env, K&lt;M, A&gt;&gt;</code> &#x2013; the return-type is <code>K&lt;M, A&gt;</code>, so no changes to <code>Env</code> can be made.</p><p>If, instead, we return <code>K&lt;M, (A Value, Env NewEnvironment)&gt;</code>, then we have a way of changing the environment being threaded through the computation.  Let&apos;s expand it out:</p><pre><code class="language-csharp">public record StateT&lt;S, M, A&gt;(Func&lt;S, K&lt;M, (A Value, S State)&gt;&gt; runState) : K&lt;StateT&lt;S, M&gt;, A&gt;
    where M : Monad&lt;M&gt;
{
    public K&lt;M, (A Value, S State)&gt; Run(S state) =&gt;
        runState(state);

   ...
}</code></pre><p>So, we&apos;ve:</p><ul><li>Renamed <code>ReaderT</code> to <code>StateT</code> </li><li>Renamed <code>runReader</code> to <code>runState</code></li><li>Changed the <code>Env</code> generic argument to <code>S</code> (for <em>&apos;state&apos;</em>)</li><li>Updated the <code>runReader</code> function to return a monad <code>M</code> with a tuple of <code>(A, S)</code> instead of just <code>A</code>.</li><li>Updated the <code>Run</code> function accordingly</li></ul><p>We also need to provide an updated <code>Bind</code> function:</p><pre><code class="language-csharp">public StateT&lt;S, M, B&gt; Bind&lt;B&gt;(Func&lt;A, StateT&lt;S, M, B&gt;&gt; f) =&gt;
    new(state =&gt; M.Bind(runState(state), tup =&gt; f(tup.Value).runState(tup.State)));</code></pre><p>This is where the key difference between the <code>ReaderT</code> and <code>StateT</code> manifests: instead of using the same <code>Env</code> value twice, note how <code>tup.State</code> is passed to the second call to <code>runState</code>.  </p><p>Let&apos;s walk through it:</p><ul><li>A <code>state</code> value is provided by the delegate</li><li>We pass that to <code>this.runState</code> &#x2013; which is a function that returns <code>K&lt;M, (A, S)&gt;</code><ul><li>That is, we are returned an <code>M</code> monad with a bound value that is an <code>(A, S)</code> tuple</li><li>The <code>S</code> in the tuple is the updated state</li></ul></li><li>Because <code>M</code> is a monad, we can pass the result of the first <code>runState</code> invocation to <code>M.Bind</code></li><li>In the bind-delegate we get a new value: <code>tup</code> which is the <code>(A, S)</code> tuple<ul><li>This tuple has the updated state in it</li></ul></li><li>We pass <code>tup.State</code> to the second <code>runState</code> &#x2013; completing the process of threading the mutated state through the computation.<ul><li>The second <code>runState</code> will also return an updated state</li></ul></li></ul><p>This is how the <code>S</code> state value is returned and threaded through the computations that are chained by the monad-bind operation.  Note, from the outside: <code>StateT&lt;S, M, A&gt;</code>, we never see the tuple (except as a result of <code>Run</code>). It&apos;s a hidden context that you never have to worry about.  </p><blockquote>This happens for every single bind operation, so we can mutate the state on every line of a LINQ expression if we wanted to.</blockquote><p>But, can&apos;t we modify the environment in a <code>ReaderT</code> monad-transformer using <code>Readable.local</code>?  What&apos;s special here?</p><p>To see the difference here, let&apos;s create a real-world example: a simple deck of cards that depletes as we deal them.</p><p>First, let&apos;s create a type that represents a single playing-card:</p><pre><code class="language-csharp">/// &lt;summary&gt;
/// Simple card type. Contains an index that can be converted to a textual
/// representation of the card.
/// &lt;/summary&gt;
public record Card(int Index)
{
    public string Name =&gt;
        (Index % 13) switch
        {
            0      =&gt; &quot;Ace&quot;,
            10     =&gt; &quot;Jack&quot;,
            11     =&gt; &quot;Queen&quot;,
            12     =&gt; &quot;King&quot;,
            var ix =&gt; $&quot;{ix + 1}&quot;
        };
    
    public string Suit =&gt;
        Index switch
        {
            &lt; 13 =&gt; &quot;Hearts&quot;,
            &lt; 26 =&gt; &quot;Clubs&quot;,
            &lt; 39 =&gt; &quot;Spades&quot;,
            &lt; 52 =&gt; &quot;Diamonds&quot;,
            _    =&gt; throw new NotSupportedException()
        };

    public override string ToString() =&gt;
        $&quot;{Name} of {Suit}&quot;;
}</code></pre><p>Next, we&apos;ll create a <code>Deck</code> of cards with a <code>generate</code> computation that creates a randomly shuffled set of 52 cards:</p><pre><code class="language-csharp">/// &lt;summary&gt;
/// Deck of cards
/// &lt;/summary&gt;
public record Deck(Seq&lt;Card&gt; Cards)
{
    public static Deck Empty = new ([]);
   
    public override string ToString() =&gt;
        Cards.ToFullArrayString();
 
    static IO&lt;Deck&gt; generate =&gt;
        IO.lift(() =&gt;
        {
            var random = new Random((int)DateTime.Now.Ticks);
            var array  = LanguageExt.List.generate(52, ix =&gt; new Card(ix)).ToArray();
            random.Shuffle(array);
            return new Deck(array.ToSeqUnsafe());
        });

    ...
}</code></pre><p>We wrap that with <code>IO.lift</code> because of the use of the <code>Random</code> type, which is, by definition, not pure &#x2013; so the <code>IO</code> monad captures the fact that each usage of <code>generate</code> should produce a different result.</p><p>We haven&apos;t used the <code>StateT</code> transformer yet, so let&apos;s start...</p><pre><code class="language-csharp">public record Deck(Seq&lt;Card&gt; Cards)
{
    ...
    
    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Deck&gt; deck =&gt;
        StateT.get&lt;OptionT&lt;IO&gt;, Deck&gt;();

    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Unit&gt; update(Deck deck) =&gt;
        StateT.put&lt;OptionT&lt;IO&gt;, Deck&gt;(deck);

    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Unit&gt; shuffle =&gt;
        from deck in generate
        from _    in update(deck)
        select unit;

    ...
}</code></pre><p>This transformer-stack has more levels than we&apos;ve used before, we have:</p><ul><li><code>StateT</code> &#x2013; for managing the <code>Deck</code> embedded state</li><li><code>OptionT</code> &#x2013; to allow us to short-cut an operation and exit</li><li><code>IO</code> &#x2013; so we can use the <code>generate</code> function and write to the console</li></ul><p>So, we have three monad effects composed into a single type.</p><blockquote>NOTE: I know the generics are a little unwieldy.  Stick with it, later on we will encapsulate all of them!</blockquote><p>The first two computations, <code>deck</code> and <code>update</code>, read and write to the <code>StateT</code> transformer state respectively.  We wrap up the <code>StateT.get</code> and <code>StateT.put</code> functions to make them slightly easier to use and more descriptive for this type. </p><p>The <code>shuffle</code> computation first generates the deck of cards using the IO <code>generate</code> operation; it then calls <code>update</code> which writes the deck-of-cards state-value into the <code>StateT</code> monad-transformer.  The state will be propagated forward automatically.  When, we return from the <code>shuffle</code> computation, that <code>Deck</code> state will still be in the <code>StateT</code> monad-transformer.</p><blockquote>This is the big difference between <code>ReaderT</code> and <code>StateT</code>: <code>ReaderT</code> can only create locally scoped changes to its environment (that it threads through the monadic computations).  Whereas <code>StateT</code> can propagate a changed state outside the scope of the change.</blockquote><p>Now that we can read and write the state of the <code>Deck</code>, we can deal some cards!</p><pre><code class="language-csharp">public record Deck(Seq&lt;Card&gt; Cards)
{
    ...
    
    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Card&gt; deal =&gt;
        from d in deck
        from c in OptionT&lt;IO&gt;.lift(d.Cards.Head)
        from _ in update(new Deck(d.Cards.Tail))
        select c;
        
    ...
}</code></pre><p>Let&apos;s walk through this:</p><ul><li>We read the <code>Deck</code> state into <code>d</code> from within the <code>StateT</code> transformer</li><li>We then <code>lift</code> into the <code>OptionT</code> transformer <code>d.Cards.Head</code><ul><li><code>d.Cards</code> is the <code>Seq&lt;Card&gt;</code> structure that we&apos;re dealing from and <code>d.Cards.Head</code> returns an <code>Option&lt;Card&gt;</code>.  <code>None</code> if there are no cards left, <code>Some(Card)</code> if there are.</li><li>So, if the sequence is empty, that means we&apos;d lift <code>None</code> into the transformer, short-cutting the operation and ending the game.  If, the sequence has cards remaining, then <code>c</code> will be assigned the first card of the sequence.</li></ul></li><li>The very next line will only be called if there are some cards in the deck and so we <code>update</code> the deck to remove the first card.</li><li>Finally, we return the <code>Card</code> that was at the head of the list.</li></ul><p>Let&apos;s add one more computation that allows us to see how many cards are remaining in the deck:</p><pre><code class="language-csharp">public record Deck(Seq&lt;Card&gt; Cards)
{
    ...

    public static StateT&lt;Deck, OptionT&lt;IO&gt;, int&gt; cardsRemaining =&gt;
        StateT.gets&lt;OptionT&lt;IO&gt;, Deck, int&gt;(d =&gt; d.Cards.Count);
        
    ...
}</code></pre><p>This uses the <code>StateT.gets</code> function, which is similar to <code>StateT.get</code> in that it accesses the state-value that is being managed by the <code>StateT</code> transformer; but it applies a mapping function before returning.  It&apos;s good practice to wrap up access to various properties of the internal state like this.  It means if we refactor the <code>Deck</code> type in the future, we only need to update those properties.</p><p>You could also map from the <code>deck</code> state:</p><pre><code class="language-csharp">public static StateT&lt;Deck, OptionT&lt;IO&gt;, int&gt; cardsRemaining =&gt;
    deck.Map(d =&gt; d.Cards.Count);</code></pre><p>They&apos;re isomorphic to each other.</p><p>With that, we&apos;ve now used all of the <em>effects</em> of the transformer stack: state-management, optional results, and IO side-effects.  </p><blockquote><em>Let&apos;s make a game...</em></blockquote><p>Before we make the game, let&apos;s make sure we can communicate with the user:</p><pre><code class="language-csharp">// Simple IO wrappers of System.Console 
public static class Console
{
    public static IO&lt;Unit&gt; writeLine(string line) =&gt;
        lift(() =&gt; System.Console.WriteLine(line));

    public static IO&lt;ConsoleKeyInfo&gt; readKey =&gt;
        lift(System.Console.ReadKey);
}
</code></pre><p>We&apos;re wrapping up the side-effecting <code>System.Console</code> into some <code>IO</code> monadic functions.  The <code>StateT</code> and <code>OptionT</code> transformers both know how to work with <code>IO</code> monads &#x2013; so this makes building a simple UI easy.</p><p>Onto the game...</p><pre><code class="language-csharp">public static class Game
{
    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Unit&gt; play =&gt;
        from _0 in Console.writeLine(&quot;First let&apos;s shuffle the cards (press a key)&quot;)
        from _1 in Console.readKey
        from _2 in Deck.shuffle
        from _4 in Console.writeLine(&quot;\nShuffle done, let&apos;s play...&quot;)
        from _5 in Console.writeLine(&quot;Dealer is waiting (press a key)&quot;)
        from _6 in deal
        select unit;
        
    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Unit&gt; deal =&gt;
        from _0   in Console.readKey
        from card in Deck.deal
        from rem  in Deck.cardsRemaining
        from _1   in Console.writeLine($&quot;\nCard dealt: {card} - {rem} cards remaining (press a key)&quot;)
        from _2   in deal
        select unit;
}
</code></pre><p>Yes, those <code>_1</code>, <code>_2</code>, <code>_3</code>, discards are hella-annoying.  For the love of god <a href="https://github.com/dotnet/csharplang?ref=paullouth.com"><code>csharplang</code></a> team, please give us wildcards in LINQ, like with lambdas!  Or, even better, allow us to just write <code>in ...</code>  instead of <code>from ... in ...</code> for discards. Each time I write these things I feel like I&apos;m back in 1985 writing BBC BASIC!</p><p>In many of the language-ext monadic-types we have an overloaded <code>&gt;&gt;</code> operator.  Which takes monads <code>ma &gt;&gt; mb</code> and binds them: <code>ma.Bind(_ =&gt; mb)</code>. What that means is: if you don&apos;t care about the result of <code>ma</code> then you can just chain the monadic computations using <code>&gt;&gt;</code>, so we can rewrite <code>play</code> (above) to not use LINQ at all:</p><pre><code class="language-csharp">public static class Game
{
    public static StateT&lt;Deck, OptionT&lt;IO&gt;, Unit&gt; play =&gt;
        Console.writeLine(&quot;First let&apos;s shuffle the cards (press a key)&quot;) &gt;&gt;
        Console.readKey &gt;&gt;
        Deck.shuffle &gt;&gt;
        Console.writeLine(&quot;\nShuffle done, let&apos;s play...&quot;) &gt;&gt;
        Console.writeLine(&quot;Dealer is waiting (press a key)&quot;) &gt;&gt;
        deal;
}
</code></pre><p>OK, OK, it&apos;s not the most enthralling of games ever made.  Simply shuffle the pack, then keep pressing a key to get the next card until they run out! Amazing!</p><p>More seriously, it&apos;s worth thinking about what we have here:</p><ul><li>No manual passing of state values as arguments &#x2013; it&apos;s handled magically</li><li>The recursive call to <code>deal</code> within the <code>deal</code> computation should be an infinite-loop.  But, it isn&apos;t, because we have <code>OptionT</code> in our transformer stack.  Meaning <code>None</code> lifted into the computation will exit this loop.  This happens when the cards run out.<ul><li>You may think that even if we can exit the recursion, we run the risk that someone would play a game so long that we&apos;d get a stack-overflow.  However, that can&apos;t happen, because the <code>IO</code> monad supports infinite recursion (without building up space leaks from an expanding stack).</li></ul></li><li>We&apos;re mixing IO with our logic...<ul><li>This isn&apos;t always a good idea (in fact you really should try to keep them separate); but it shows that combining IO (including asynchronous IO) with other complex logic like state-management and optional results is now possible.  </li><li>In the past I would have had to build a bespoke <code>StateOptionAsync</code> type to get these combined behaviours.  Now you can build them yourself.</li></ul></li></ul><blockquote>What is really interesting about the code above (in my humble opinion) is how minimal and uncluttered this is. We are really getting down to the essence of function rather than having to wade through boilerplate.  But we can go even further...</blockquote><h2 id="i-really-want-a-game">I really want a game!</h2><p>I wanted to keep this article more concise.  But, during the writing of it, I ended up expanding on the card-game idea and made a fully-fledged version of Pontoon (or 21, or Vingt-Un, whatever it&apos;s called where you live)!</p><p>As mentioned earlier, the generics of 3-deep transformers should be encapsulated in a bespoke type.  <a href="https://github.com/louthy/language-ext/blob/main/Samples/CardGame/Game.Monad/Game.cs?ref=paullouth.com">So, here is <code>Game&lt;A&gt;</code>, which encapsulates <code>StateT&lt;GameState, OptionT&lt;IO&gt;, A&gt;</code></a>.</p><p>The state we&apos;re managing, <code>GameState</code>, contains the players, the deck, and a &apos;current player&apos; &#x2013; which allows for contextual blocks of code where we are dealing with a single player:</p><pre><code class="language-csharp">public record GameState(
    HashMap&lt;Player, PlayerState&gt; State, 
    Deck Deck, 
    Option&lt;Player&gt; CurrentPlayer)
{
    public static readonly GameState Zero = new ([], Deck.Empty, None);
}</code></pre><p>All of the methods in <code>Game&lt;A&gt;</code> defer to the <a href="https://github.com/louthy/language-ext/blob/main/Samples/CardGame/Game.Monad/Game.Monad.cs?ref=paullouth.com">trait implementations in <code>Game</code></a>:</p><pre><code class="language-csharp">public partial class Game :
    Deriving.MonadIO&lt;Game, StateT&lt;GameState, OptionT&lt;IO&gt;&gt;&gt;,
    Deriving.Choice&lt;Game, StateT&lt;GameState, OptionT&lt;IO&gt;&gt;&gt;,
    Deriving.Stateful&lt;Game, StateT&lt;GameState, OptionT&lt;IO&gt;&gt;, GameState&gt;
{
    public static K&lt;StateT&lt;GameState, OptionT&lt;IO&gt;&gt;, A&gt; Transform&lt;A&gt;(K&lt;Game, A&gt; fa) =&gt;
        fa.As().runGame;

    public static K&lt;Game, A&gt; CoTransform&lt;A&gt;(K&lt;StateT&lt;GameState, OptionT&lt;IO&gt;&gt;, A&gt; fa) =&gt; 
        new Game&lt;A&gt;(fa.As());
}</code></pre><ul><li><code>Game</code> implements <code>MonadIO&lt;Game&gt;</code>, <code>Stateful&lt;Game, GameState&gt;</code>, and <code>Choice&lt;Game&gt;</code> traits leveraging the <code>Deriving</code> automatic trait-implementations that defer to the wrapped transformer.  </li><li><a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Stateful/Stateful.Trait.cs?ref=paullouth.com"><code>Stateful</code></a> is the state-equivalent of <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Readable/Readable.Trait.cs?ref=paullouth.com"><code>Readable</code></a> from the last article &#x2013;  it generalises the idea of reading and writing state for a structure and is equivalent to <code>MonadState</code> in Haskell.  </li></ul><p>By encapsulating the monad-transformer stack into a new type like this, we get much more elegant code. Here&apos;s the <a href="https://github.com/louthy/language-ext/blob/main/Samples/CardGame/Game.cs?ref=paullouth.com">entry point to the game</a>:</p><pre><code class="language-csharp">// Play the game!
public static Game&lt;Unit&gt; play =&gt;
    Display.askPlayerNames &gt;&gt;
    enterPlayerNames       &gt;&gt;
    Display.introduction   &gt;&gt;
    Deck.shuffle           &gt;&gt;
    playHands;</code></pre><p>Note how we&apos;re now using the <code>Game&lt;A&gt;</code> monad that wraps the <code>StateT&lt;OptionT&lt;IO&gt;, A&gt;</code> transformer-stack.  Also note, we have encapsulated the <code>Console.writeLine</code> operations into specific <code>Display</code> computations (the thinking here is that you&apos;d want to localise the text, so  wrapping up the UI functionality would make sense).</p><blockquote>Again, this is now really at the essence of the functionality.  We are almost at zero boilerplate.</blockquote><p>We then keep looping, playing many hands until either the deck runs out of cards, or the users quit:</p><pre><code class="language-csharp">// Play many hands until the players decide to quit
static Game&lt;Unit&gt; playHands =&gt;
    from _   in initPlayers &gt;&gt;
                playHand &gt;&gt;
                Display.askPlayAgain
    from key in Console.readKey
    from __  in when(key.Key == ConsoleKey.Y, playHands)
    select unit;
</code></pre><p>A hand starts with two cards being dealt to the players (<code>dealHands</code>), then a loop of sticking or twisting by the users (<code>playRound</code>), followed by an end-of-game winner announcement (<code>gameOver</code>) and showing of the current deck status:</p><pre><code class="language-csharp">// Play a single hand
static Game&lt;Unit&gt; playHand =&gt;
    dealHands &gt;&gt;
    playRound &gt;&gt;
    gameOver  &gt;&gt;
    Display.cardsRemaining;
</code></pre><p>The <code>playRound</code> operation leverages the <code>Prelude.when</code> function that evaluates a monad with a bound <code>bool</code> value, if it&apos;s <code>true</code> then the operation passed to it is evaluated too:</p><pre><code class="language-csharp">static Game&lt;Unit&gt; playRound =&gt;
    when(isGameActive,
         from _ in Players.with(activePlayers, stickOrTwist) 
         from r in playRound
         select r)
        .As();
</code></pre><p><code>isGameActive</code> checks various facts (in the <code>GameState</code>) to see if the game is finished (have the players all bust, or stuck, or are at 21, ...).  Pontoon is quite complex, because a player can have multiple possible scores if they&apos;re holding aces and so this check needs to take that into account.</p><p><code>Players.with</code> evaluates <code>activePlayers</code> which returns the players still in the game and then traverses each player, setting the <code>CurrentPlayer</code> property in the <code>GameState</code>, and then invokes the provided operation <code>stickOrTwist</code> with the current-player context set:</p><p><strong>Players.with:</strong></p><pre><code class="language-csharp">public static Game&lt;Unit&gt; with&lt;A&gt;(GameM&lt;Seq&lt;Player&gt;&gt; playersM, Game&lt;A&gt; ma) =&gt;
    playersM.Bind(ps =&gt; with(ps, ma))
            .Map(_ =&gt; unit);

public static Game&lt;Unit&gt; with&lt;A&gt;(Seq&lt;Player&gt; players, Game&lt;A&gt; ma) =&gt;
    players.Traverse(p =&gt; Player.with(p, ma)).
            Map(_ =&gt; unit)
           .As();</code></pre><p><strong>Player.with</strong></p><pre><code class="language-csharp">public static Game&lt;A&gt; with&lt;A&gt;(Player player, Game&lt;A&gt; ma) =&gt;
    Stateful.local&lt;Game, GameState, A&gt;(setCurrent(player), ma).As();
</code></pre><blockquote>Note the use of <code>Stateful.local</code> in <code>Player.with</code>.  It creates a local state with which to run the <code>ma</code> operation.  The state is automatically reset once the <code>ma</code> operation has completed.  This is similar to <code>Readable.local</code>. </blockquote><p>Then we move on to the per-player querying of whether they want to stick or twist (whether they want a new card or not).  We check again if the game is still active as turns by other players may have put the game into a &apos;game over&apos; state.</p><pre><code class="language-csharp">static Game&lt;Unit&gt; stickOrTwist =&gt;
    when(isGameActive,
         from _      in Display.askStickOrTwist &gt;&gt;
                        Player.showCards
         from key    in Console.readKey
         from __     in key.Key switch
                        {
                            ConsoleKey.S =&gt; Player.stick,
                            ConsoleKey.T =&gt; twist,
                            _            =&gt; stickOrTwistBerate
                        }
         select unit)
        .As();
</code></pre><p>So, we get the current player (which is in the <code>GameState</code>), ask them whether they want to stick or twist, show them their cards, and then wait for them to press <code>S</code> or <code>T</code> on the keyboard.  We then either run <code>Player.stick</code> (which updates a flag in the <code>PlayerState</code> within the <code>GameState</code>), or <code>twist</code>, which will deal a new card...</p><pre><code class="language-csharp">static Game&lt;Unit&gt; twist =&gt;
    from card in Deck.deal
    from _    in Player.addCard(card) &gt;&gt; 
                 Display.showCard(card) &gt;&gt;
                 when(Player.isBust, Display.bust)
    select unit;
</code></pre><p>In this short function we update the state of the deck by dealing a new card (<code>Deck.deal</code>), we update the state of the player to register the card they have been dealt (<code>Player.addCard</code>), we do some IO to show the card (<code>Display.showCard</code>), and then we look at the player&apos;s state to see if they&apos;re bust, and if so, tell them.</p><p>Finally, here&apos;s the <code>gameOver</code> operation:</p><pre><code class="language-csharp">static Game&lt;Unit&gt; gameOver =&gt;
    from ws in winners
    from ps in playersState
    from _  in Display.winners(ws) &gt;&gt;
               Display.playerStates(ps)
    select unit;</code></pre><p>We get the state of all of the players and the winner(s), and then display them. Simple! But, behind the scenes there&apos;s lots of state-querying going on, yet we don&apos;t see that.</p><p>What I really like about this approach is how most of the clutter just disappears.  It can make the code extremely clear and declarative. It should also be clear why it makes sense to encapsulate the transformer into a new type.  If we decide to change the transformer, the game code doesn&apos;t need to change, that means we have super-refactoring opportunities.  Either for performance or to add new capabilities to the <code>Game&lt;A&gt;</code> monad.</p><p>Here&apos;s some example output from a game:</p><pre><code class="language-text">Enter a player name, or just press enter complete
Paul
&apos;Paul&apos; added to the game
Adam
&apos;Adam&apos; added to the game
Orla
&apos;Orla&apos; added to the game

Let&apos;s play...
Paul [2 of Hearts, Jack of Spades], possible scores [12]
Orla [4 of Diamonds, 10 of Clubs], possible scores [14]
Adam [6 of Spades, 2 of Diamonds], possible scores [8]
Paul, stick or twist? (S/T)
        [2 of Hearts, Jack of Spades], possible scores [12], high-score: 14
t
        8 of Clubs
Orla, stick or twist? (S/T)
        [4 of Diamonds, 10 of Clubs], possible scores [14], high-score: 20
t
        9 of Clubs
        Bust!
Adam, stick or twist? (S/T)
        [6 of Spades, 2 of Diamonds], possible scores [8], high-score: 20
t
        9 of Hearts
Paul, stick or twist? (S/T)
        [2 of Hearts, Jack of Spades, 8 of Clubs], possible scores [20], high-score: 20
s
Adam, stick or twist? (S/T)
        [6 of Spades, 2 of Diamonds, 9 of Hearts], possible scores [17], high-score: 20
t
        Ace of Clubs
Adam, stick or twist? (S/T)
        [6 of Spades, 2 of Diamonds, 9 of Hearts, Ace of Clubs], possible scores [18, 28], high-score: 20
t
        6 of Diamonds
        Bust!
Paul is the winner with 20!
Paul [2 of Hearts, Jack of Spades, 8 of Clubs], possible scores [20] [STICK]
Orla [4 of Diamonds, 10 of Clubs, 9 of Clubs], possible scores [23]
Adam [6 of Spades, 2 of Diamonds, 9 of Hearts, Ace of Clubs, 6 of Diamonds], possible scores [24, 34]
41 cards remaining in the deck
Play again (Y/N)
</code></pre><h2 id="note-of-caution">Note of caution</h2><p>One note of caution though.  Although this leads to quite terse code, the state (other than its type) is a little opaque.  We could easily modify some state within one of these functions and the caller wouldn&apos;t know.  So, the state-monad approach could be problematic application-wide if not managed correctly (they act like global variables to a certain extent).</p><p>Also, in a real-world application, you&apos;d want to separate the game-logic by partitioning it into pure functions that work over the <code>GameState</code> and keep it away from the IO code (separation of concerns).  This interleaving of logic and IO works at this small scale but is problematic for a fully-fledged application.  It does however show how we can get down to the essence of the underlying logic.</p><h2 id="asynchrony">Asynchrony</h2><p>One useful side-effect of managing state like this is that if you have an <code>IO</code> monad in your <code>StateT</code> transformer stack (as we have in these examples) then if you call <code>forkIO</code> to do some parallel processing (or use some of the auto-parallel processing, like <code>Traverse</code>) then, because of the pure nature of these expressions, each fork would get their own branched state that would be managed without affecting each other.  So, even though this approach sometimes feels like we&apos;re using global-variables, the &apos;stateful expressions&apos; are in fact pure expressions and updates are done immutably.  </p><p>Here&apos;s a quick example:</p><pre><code class="language-csharp">public static class StateForkIO
{
    public static StateT&lt;int, IO, Unit&gt; forkTest =&gt;
        from p1 in showState(&quot;parent&quot;)
        from f1 in fork(countTo10(&quot;fst&quot;))
        from f2 in fork(countTo10(&quot;snd&quot;))
        from _  in awaitAll(f1, f2)
        from p2 in showState(&quot;parent&quot;)
        select unit;

    static StateT&lt;int, IO, Unit&gt; countTo10(string branch) =&gt;
        from _1 in addToState
        from st in showState(branch)
        from _2 in when(st &lt; 10, countTo10(branch))
        select unit;

    static StateT&lt;int, IO, Unit&gt; addToState =&gt;
        StateT.modify&lt;IO, int&gt;(x =&gt; x + 1);
    
    static StateT&lt;int, IO, int&gt; showState(string branch) =&gt;
        from s in StateT.get&lt;IO, int&gt;()
        from _ in Console.writeLine($&quot;{branch}: {s}&quot;)
        select s;
}</code></pre><p>The <code>forkTest</code> operation displays the current-state (an <code>int</code>) and then forks two <code>countTo10</code> operations.  They run independently.  The <code>forkTest</code> operation then awaits the completion of those forked operations.</p><p>The <code>countTo10</code> operation keeps looping, adding <code>1</code> to its state, until it gets to <code>10</code>, it then exits.  On each iteration it writes its state value to the console.</p><p>Once both operations have completed, the <code>forkTest</code> operation writes its state to the console.</p><p>If we run it with an initial state of <code>0</code>:</p><pre><code class="language-csharp">StateForkIO.forkTest
           .Run(0)
           .Run()
           .Ignore();</code></pre><p>Then we get the following output:</p><pre><code class="language-csharp">parent: 0
fst: 1
snd: 1
fst: 2
snd: 2
fst: 3
fst: 4
snd: 3
snd: 4
fst: 5
snd: 5
fst: 6
snd: 6
fst: 7
snd: 7
fst: 8
snd: 8
fst: 9
snd: 9
fst: 10
snd: 10
parent: 0
</code></pre><p>So you can see the two <code>countTo10</code> operations are running in parallel. But it&apos;s also clear they have their own local state.  They each start at <code>1</code> and finish at <code>10</code>.  And the <code>parent</code> thread, that created the two forks, hasn&apos;t had its state changed at all.</p><p>And, just in case you&apos;re thinking that the forks are not inheriting the parent&apos;s state.  Let&apos;s run the <code>forkTest</code> with an initial value of <code>5</code>:</p><pre><code class="language-csharp">parent: 5
fst: 6
snd: 6
fst: 7
snd: 7
fst: 8
fst: 9
snd: 8
snd: 9
fst: 10
snd: 10
parent: 5</code></pre><p>This stateful thread-safety can be leveraged and depending on the use case could be quite powerful. For example, let&apos;s say the card-game wasn&apos;t just a simple console app, but was a networked game.  We could fork our network communications code, setting the <code>CurrentPlayer</code> state for each fork.  So, we&apos;d have multiple current-players all interacting with their own state independently.</p><p>If you want to bring stateful changes back to the parent, then you need to bring a result value back via <code>forkedOp.Await</code> and then set it in the parent context.  Which is quite a nice synchronisation technique in its own right.</p><blockquote>I hope that gives you a bit more insight into how the state isn&apos;t really a global variable. It&apos;s much more powerful than that.  But still, it&apos;s always worth considering how you propagate state through an application.</blockquote><h2 id="conclusion">Conclusion</h2><p>My desire for something more concise got out of hand.  My bad.  But, with the fully worked out Pontoon application, you can dig into how I&apos;ve made the game-logic terse and elegant.  Real-world examples always tend to be a bit more inspiring, I think.  Make sure to look at the support functions to see how everything has been encapsulated.</p><p>The full game source-code <a href="https://github.com/louthy/language-ext/tree/main/Samples/CardGame?ref=paullouth.com">can be found here</a>.  </p><p><em>Next up: </em><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-12-writert-monad-transformer/"><em>Part 12, the <code>WriterT</code> monad-transformer</em></a></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 10- ReaderT monad transformer]]]></title><description><![CDATA[A look at the ReaderT monad transformer and the general Readable trait that allows generalised access to types with embedded environments.]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-10-readert-monad-transformer/</link><guid isPermaLink="false">667827eb98be6a03e27d0995</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[functor]]></category><category><![CDATA[monad]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[hkt]]></category><category><![CDATA[traits]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Wed, 26 Jun 2024 11:40:17 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/06/readert.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/06/readert.png" alt="Higher Kinds in C# with language-ext [Part 10- ReaderT monad transformer]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow this &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/">Part 8 - Monads (continued)</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-9-monad-transformers/">Part 9 - Monad Transformers</a></li></ul><p>In the last article we started looking into monad transformers.  We mostly focused on the <code>MaybeT</code> transformer (<code>OptionT</code> in <a href="https://github.com/louthy/language-ext?ref=paullouth.com">language-ext</a>), lifting the <code>IO</code> monad <em>into it</em> to create an optional side-effect.  </p><p>Later in the article I did a quick overview of a project (that I am working on) that creates <em>&apos;domain monads&apos;</em> by wrapping monad-transformer stacks into new types that are then further composed with free-monads to create a small application architecture. </p><p>There is never a <em>&apos;right way&apos;</em> to structure an application and I think it&apos;s risky to use blogs, or other short-form methods to share coding advice on the <em>&apos;one true way&apos;</em>, because it doesn&apos;t exist. However, I think when you see how domains, layers, components, and structure in-general, evolves out of compositional types (like monads and monad-transformers) then that light-bulb moment will happen where you can suddenly <em>&apos;see&apos;</em> the structure of your architecture from 10,000 feet. </p><p>These moments of clarity were always missing for me in my former OOP life, whereas with the pure functional programming approach I feel I have total clarity, but also it feels like the architecture is fluid and malleable (it can change with requirements) in a way that just isn&apos;t there in the object-oriented world.  This may well be a personal thing, so please don&apos;t take this as me saying &quot;there&apos;s exactly one way to write code&quot; &#x2013; because all self-appointed internet experts really should be taken with a handful of salt!</p><blockquote>Even though the architecture example (from the last article) was a small example, I hope that it whetted your appetite when thinking about how to use pure functional programming techniques to create structure in your programs!</blockquote><p>To really benefit the most from this approach we should aim to make our <em>entire code-base</em> pure and getting the architecture right is part of that story.  What I find valuable about this approach is that <em>the architecture itself becomes composable. </em>That&apos;s quite profound when you think about it and it certainly changes the way I write code now.</p><p>It was quite a lot to take in, of course, and I certainly wouldn&apos;t expect novice FP devs to get it straight-away.  But, one of the biggest issues I&apos;ve had with building <a href="https://github.com/louthy/language-ext?ref=paullouth.com">language-ext</a> has been how to put control of building functional types into the hands of the users of the library.  Before the higher-kinds approach (demonstrated in this series) there was no way to write code that worked for <em>all</em> monads, or <em>all</em> functors, etc.  <em>Now you can.</em>  </p><p>And before we had monad-transformers there was no way to compose the monads that already existed into new &apos;super monads&apos;, which meant I was stuck writing <code>OptionAsync</code>, <code>EitherAsync</code>, <code>TryOption</code>, and other combination-monads.  And you were stuck waiting for me to build various pre-combined monads. <em>This issue no longer exists.</em></p><blockquote>These abstractions now exist. And many of the core types needed for you to build your own functional stacks now exist. The days of waiting for me to build <code>ValidationAsync&lt;F, A&gt;</code> are over, just use the <code>ValidationT&lt;F, IO, A&gt;</code> monad transformer stack.</blockquote><p>It may take a little while for the implications of the changes in <code>v5</code> of language-ext to really materialise as opportunities for you.  It&apos;s a style of programming and an approach to composition that just hasn&apos;t existed in C# to-date.  So, unless you&apos;ve come from a Haskell background, this might not seem to be quite as profound as it really is.  </p><p>C# isn&apos;t Haskell of course, but the reason for all of this isn&apos;t to make C# into Haskell, it&apos;s to make the inertia of the C# developer <em>track in the direction of pure functional programming.</em> And it just so happens that Haskell (as a pure functional programming language) has solved many patterns we need and so the inspiration often comes from that language.</p><p><em>Let&apos;s take a look at another monad-transformer...</em></p><h2 id="readertenv-m-a">ReaderT&lt;Env, M, A&gt;</h2><p>The <code>ReaderT</code> monad-transformer adds a <em>static</em> environment, <code>Env</code>, to a given monad <code>M</code>.  We briefly covered the <code>Reader&lt;Env, A&gt;</code> monad in the <a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/">Monads Continued article</a> &#x2013; this generalises the idea into a monad-transformer. So, for example, let&apos;s say we had some application configuration in a simple record type:</p><pre><code class="language-csharp">public record MyConfig(string SourceFolder);</code></pre><p>We want to write pure code, so we can&apos;t just stick this in a global <code>static</code> variable.  </p><p>One option is to pass it as an argument to every function that needs the configuration settings:</p><pre><code class="language-csharp">public static IO&lt;string&gt; readSourceText(string file, MyConfig config)
{
    var path = Path.Combine(config.SourceFolder, file);
    return IO.liftAsync(e =&gt; File.ReadAllTextAsync(path, e.Token));
}</code></pre><p>This is perfectly valid, but it can start to get a bit messy and annoying.  And, aside from the name of the type, it&apos;s not very declarative.  If <code>MyConfig</code> had a less descriptive name then it might make the interface to the function more confusing.</p><p>Instead, we drop the <code>MyConfig</code> argument and use the <code>ReaderT</code> monad-transformer.  We can stack it with the <code>IO</code> monad to get both a static environment and side-effects.  </p><p><code>ReaderT</code> will automatically thread the <code>MyConfig</code> value through the computation for us and do so declaratively:</p><pre><code class="language-csharp">public static ReaderT&lt;MyConfig, IO, string&gt; readSourceText(string file) =&gt;
    from config in ReaderT.ask&lt;IO, MyConfig&gt;()
    let path = Path.Combine(config.SourceFolder, file)
    from text in IO.liftAsync(e =&gt; File.ReadAllTextAsync(path, e.Token))
    select text;
</code></pre><p>Notice how there isn&apos;t a <code>MyConfig</code> value passed as an argument to <code>readSourceText</code>. It somehow magics the configuration out of thin air!</p><p>The key to this is on the first line in the LINQ expression:</p><pre><code class="language-csharp">ReaderT.ask&lt;IO, MyConfig&gt;()</code></pre><p>This <code>static</code> function: <code>ask</code>, somehow gets the <code>MyConfig</code> structure and loads it into the <code>config</code> variable.  How can a <code>static</code> function retrieve a non-global state?</p><p>If we look at the <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/Reader/ReaderT/ReaderT.cs?ref=paullouth.com">definition of <code>ReaderT&lt;Env, M, A&gt;</code></a> we&apos;ll get some clues:</p><pre><code class="language-csharp">public record ReaderT&lt;Env, M, A&gt;(Func&lt;Env, K&lt;M, A&gt;&gt; runReader) : K&lt;ReaderT&lt;Env, M&gt;, A&gt;
    where M : Monad&lt;M&gt;
{
    public K&lt;M, A&gt; Run(Env env) =&gt; 
        this.runReader(env);   

   ...    
}</code></pre><p>Internally, <code>ReaderT</code> is a <code>Func&lt;Env, K&lt;M, A&gt;&gt;</code>. If we provide an <code>Env</code> then we get a <code>K&lt;M, A&gt;</code> back (which is constrained to be a <code>Monad&lt;M&gt;</code>). </p><blockquote>This follows the transformer pattern.  Except this is a little different to <code>MaybeT</code> and <code>OptionT</code> in that <code>K&lt;M, A&gt;</code> is the <em>inner</em> type, whereas with <code>MaybeT</code> and <code>OptionT</code> it was the <em>outer</em> type: <code>K&lt;M, Option&lt;A&gt;&gt;</code>. </blockquote><blockquote>This difference in implementation is all to do with what is best for the particular transformer.  It makes sense to provide an environment for the inner monad to run in.  Whereas, for the optional types, it makes sense for the result to be optional! In general, optional types are wrapped by the lifted monad, and stateful-computation types wrap the lifted monad.  </blockquote><p>When we come to run the <code>ReaderT</code> transformer, we must pass the configuration value to it, so it can be passed through the computation:</p><pre><code class="language-csharp">// Create the application configuration object.  
// Typically you would do this once
var configObj = new MyConfig(&quot;c:\\folder&quot;);

// Run the ReaderT.  This returns an IO&lt;string&gt;
var configTextIO = readSourceText(&quot;test.cs&quot;).Run(configObj);
</code></pre><p>The result is an <code>IO&lt;string&gt;</code>. The <code>IO</code> monad being that which was lifted into the transformer.  </p><p>If we run the <code>IO</code> value then we get the raw text:</p><pre><code class="language-csharp">var configText = configTextIO.Run();</code></pre><blockquote>Reminder: You shouldn&apos;t exit the <code>IO</code> monad unless you&apos;re at the very edge of your application.</blockquote><p>That doesn&apos;t explain how <code>ask</code> works from earlier.  It somehow magicked the configuration out of thin air. Remember, we&apos;re working with a wrapped function here, which means we can defer the gathering of the configuration (make it lazy):</p><pre><code class="language-csharp">new ReaderT&lt;Env, M, Env&gt;(env =&gt; M.Pure(env));</code></pre><p>So, we don&apos;t need to know the environment to implement <code>ask</code>, we just need to know we will be given it at some point.  Here we take the <code>env</code> input and simply lift it into the <code>M</code> monad which exposes it as the bound value.  Extremely simple, but also extremely effective.</p><p>It can be simplified further to:</p><pre><code class="language-csharp">new ReaderT&lt;Env, M, Env&gt;(M.Pure);</code></pre><p>And even further when it&apos;s part of a function that can infer the return type:</p><pre><code class="language-csharp">public static ReaderT&lt;Env, M, Env&gt; ask&lt;Env, M&gt;() 
    where M : Monad&lt;M&gt; =&gt;
    new (M.Pure);
</code></pre><p>Everything in <code>ReaderT</code> therefore is lazy.  We know the <code>Run</code> method will provide an <code>Env</code> value which we can use to invoke the encapsulated delegate and realise a concrete result.  But, every other (non-<code>Run</code>) method on <code>ReaderT</code> must use standard function composition to achieve its behaviours.  </p><p>For example, the <code>Bind</code> function:</p><pre><code class="language-csharp">public ReaderT&lt;Env, M, B&gt; Bind&lt;B&gt;(Func&lt;A, ReaderT&lt;Env, M, B&gt;&gt; f) =&gt;
    new(env =&gt; M.Bind(runReader(env), x =&gt; f(x).runReader(env)));</code></pre><p>We create a new <code>Func</code> that provides us with an <code>Env env</code>, we invoke our <code>runReader</code> function with the <code>env</code> value.  It gives us the wrapped <code>K&lt;M, A&gt;</code> which we can <code>M.Bind</code> because it&apos;s constrained to be a <code>Monad&lt;M&gt;</code>.  That gets us the <code>A</code> value from within the <code>M</code> monad (assigned to <code>x</code>).  We pass the <code>A</code> to the <code>f</code> function provided.  It returns a new <code>ReaderT</code> which we then invoke (with the same <code>env</code>).  It returns a <code>K&lt;M, B&gt;</code> which is what <code>M.Bind</code> expects as a result!</p><p>This is how the environment is threaded through the monad-transformer and how it can be made available for use in the LINQ expression.  The <code>env</code> is always available because every <code>ReaderT</code> has it given when invoked.</p><h3 id="readable">Readable</h3><p>So, that&apos;s all awesome and everything, but when we use transformers it&apos;s often good to wrap up the stack into a new type for encapsulation reasons.  The eagle eyed among you may realise that <code>ReaderT&lt;Env, IO, A&gt;</code> is essentially <code>Eff&lt;RT, A&gt;</code> from previous versions of language-ext. The <code>Eff</code> monad was designed to be an IO monad with a &apos;runtime&apos; that allowed for injectable side-effects.</p><p>So, let&apos;s wrap it up and create our own simplified <code>Eff</code> monad.  First, let&apos;s create the <code>Eff&lt;RT, A&gt;</code> type:</p><pre><code class="language-csharp">public record Eff&lt;RT, A&gt;(ReaderT&lt;RT, IO, A&gt; runEff) : K&lt;Eff&lt;RT&gt;, A&gt;;</code></pre><p>This simply wraps the <code>ReaderT&lt;RT, IO, A&gt;</code> monad transformer.</p><p>Next, let&apos;s make <code>Eff&lt;RT, A&gt;</code> into a monad by implementing the <code>Monad</code> trait:</p><pre><code class="language-csharp">public class Eff&lt;RT&gt; : Monad&lt;Eff&lt;RT&gt;&gt;
{
    public static K&lt;Eff&lt;RT&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;Eff&lt;RT&gt;, A&gt; ma, Func&lt;A, K&lt;Eff&lt;RT&gt;, B&gt;&gt; f) =&gt;
        new Eff&lt;RT, B&gt;(ma.As().runEff.Bind(x =&gt; f(x).As().runEff));

    public static K&lt;Eff&lt;RT&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Eff&lt;RT&gt;, A&gt; ma) =&gt;
        new Eff&lt;RT, B&gt;(ma.As().runEff.Map(f));

    public static K&lt;Eff&lt;RT&gt;, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Eff&lt;RT, A&gt;(ReaderT.Pure&lt;RT, IO, A&gt;(value));

    public static K&lt;Eff&lt;RT&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;Eff&lt;RT&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;Eff&lt;RT&gt;, A&gt; ma) =&gt;
        new Eff&lt;RT, B&gt;(mf.As().runEff.Apply(ma.As().runEff).As());

    public static K&lt;Eff&lt;RT&gt;, A&gt; LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
        new Eff&lt;RT, A&gt;(ReaderT.liftIO&lt;RT, IO, A&gt;(ma));
}
</code></pre><p>Note how every method is just a wrapper around the calls to the <code>ReaderT</code> implementations (<code>runEff</code> is a <code>ReaderT&lt;RT, IO, A&gt;</code>).  Also note that we have implemented <code>LiftIO</code> which isn&apos;t enforced (there&apos;s a default implementation) but this allows us to use <code>IO</code> operations in our LINQ expressions directly (we covered this in the last article).</p><p>Next, create our <code>As</code> and <code>Run</code> extensions and add some constructors:</p><pre><code class="language-csharp">public static class Eff
{
    public static Eff&lt;RT, A&gt; As&lt;RT, A&gt;(this K&lt;Eff&lt;RT&gt;, A&gt; ma) =&gt;
        (Eff&lt;RT, A&gt;)ma;

    public static IO&lt;A&gt; Run&lt;RT, A&gt;(this K&lt;Eff&lt;RT&gt;, A&gt; ma, RT runtime) =&gt;
        ma.As().runEff.Run(runtime).As();

    public static Eff&lt;RT, A&gt; Pure&lt;RT, A&gt;(A value) =&gt;
        new (ReaderT.Pure&lt;RT, IO, A&gt;(value));

    public static Eff&lt;RT, A&gt; Fail&lt;RT, A&gt;(Error error) =&gt;
        new (ReaderT.liftIO&lt;RT, IO, A&gt;(IO.Fail&lt;A&gt;(error)));
}
</code></pre><p>And that&apos;s it!</p><p>Of course, the real <code>Eff</code> monad comes with lots of helper functions that make working with effects easier.  But pretty much everything is just lifting the existing functionality from the transformers into the <code>Eff</code> type. For example, to access the runtime is simply a <code>ReaderT.ask</code>:</p><pre><code class="language-csharp">public static Eff&lt;RT, RT&gt; runtime&lt;RT&gt;() =&gt;
    new (ReaderT.ask&lt;IO, RT&gt;());
</code></pre><p>You should be getting the idea now that this is just a wrapper around the transformer stack.  We could extend the capabilities by stacking more transformers if necessary.  </p><p>The real reason I wanted to demonstrate this is because there is another trait-type especially for <em>readers</em>.  It&apos;s called: <code>Readable</code> and any type that implements it becomes &apos;readable&apos;:</p><pre><code class="language-csharp">public interface Readable&lt;M, Env&gt;
    where M : Readable&lt;M, Env&gt;
{
    public static abstract K&lt;M, A&gt; Asks&lt;A&gt;(Func&lt;Env, A&gt; f);

    public static virtual K&lt;M, Env&gt; Ask =&gt;
        M.Asks(Prelude.identity);

    public static abstract K&lt;M, A&gt; Local&lt;A&gt;(
        Func&lt;Env, Env&gt; f,
        K&lt;M, A&gt; ma);
}</code></pre><blockquote>For those who know Haskell, this is essentially <code>MonadReader</code> without inheriting the <code>Monad</code> constraint!</blockquote><p>We can add it to the traits that <code>Eff&lt;RT&gt;</code> implements:</p><pre><code class="language-csharp">public class Eff&lt;RT&gt; : Monad&lt;Eff&lt;RT&gt;&gt;, Readable&lt;Eff&lt;RT&gt;, RT&gt;
{
    // ... implementations from earlier ...

    public static K&lt;Eff&lt;RT&gt;, A&gt; Asks&lt;A&gt;(Func&lt;RT, A&gt; f) =&gt;
        new Eff&lt;RT, A&gt;(ReaderT&lt;RT, IO, A&gt;.Asks(f));

    public static K&lt;Eff&lt;RT&gt;, A&gt; Local&lt;A&gt;(Func&lt;RT, RT&gt; f, K&lt;Eff&lt;RT&gt;, A&gt; ma) =&gt;
        new Eff&lt;RT, A&gt;(ma.As().runEff.Local(f));
}    
</code></pre><p><code>Readable</code> just abstracts the idea of accessing a static environment away from the monad.  It means we can write code that accepts any &apos;readable&apos; type, whether it&apos;s <code>Eff</code>, <code>ReaderT</code>, <code>Reader</code>, or whatever bespoke type we have built.  </p><p><code>Readeable</code> also comes with some static functions that makes readable types easy to work with:</p><pre><code class="language-csharp">public static class Readable
{
    public static K&lt;M, Env&gt; ask&lt;M, Env&gt;()
        where M : Readable&lt;M, Env&gt; =&gt;
        M.Ask;

    public static K&lt;M, A&gt; asks&lt;M, Env, A&gt;(Func&lt;Env, A&gt; f)
        where M : Readable&lt;M, Env&gt; =&gt;
        M.Asks(f);

    public static K&lt;M, A&gt; asksM&lt;M, Env, A&gt;(Func&lt;Env, K&lt;M, A&gt;&gt; f)
        where M : Readable&lt;M, Env&gt;, Monad&lt;M&gt; =&gt;
        M.Flatten(M.Asks(f));

    public static K&lt;M, A&gt; local&lt;M, Env, A&gt;(Func&lt;Env, Env&gt; f, K&lt;M, A&gt; ma)
        where M : Readable&lt;M, Env&gt; =&gt;
        M.Local(f, ma);
}
</code></pre><p>Let&apos;s say our &apos;runtime&apos; was just an <code>int</code> and we want to write a function that takes two <code>Eff</code> monads with <code>int</code> as their bound-values and then <em>sum</em> those values with the <code>int</code> that&apos;s in the runtime (the environment).</p><pre><code class="language-csharp">public static K&lt;Eff&lt;int&gt;, int&gt; addEff(Eff&lt;int, int&gt; mx, Eff&lt;int, int&gt; my) =&gt;
   from x in mx
   from y in my
   from z in Eff.runtime&lt;int&gt;()
   select x + y + z;</code></pre><p>This works just fine, we can access the runtime value via the <code>Eff.runtime</code> function. However, this function only works with one monadic type: <code>Eff</code>.</p><p>We can generalise it even further:</p><pre><code class="language-csharp">public static K&lt;M, int&gt; addRdr&lt;M&gt;(K&lt;M, int&gt; mx, K&lt;M, int&gt; my)
    where M : Readable&lt;M, int&gt;, Monad&lt;M&gt; =&gt;
    from x in mx
    from y in my
    from z in Readable.ask&lt;M, int&gt;()
    select x + y + z;
</code></pre><p>Note how <code>M</code> is not only constrained to be a <code>Monad&lt;M&gt;</code> but it is also constrained to be a <code>Readable&lt;M, int&gt;</code>.  So, it&apos;s bindable and readable!  Let&apos;s try running it with some <code>Eff</code> monads:</p><pre><code class="language-csharp">var compute = addRdr(Eff.Pure&lt;int, int&gt;(100), Eff.Pure&lt;int, int&gt;(200));
var result = compute.Run(300).Run();  // 600
</code></pre><p><code>addRdr</code> has no idea what monad we&apos;re running and it has no idea how we&apos;re managing our static environment.  It is a complete abstraction away from the internals.  The <code>Eff</code> monad supports IO side-effects, parallelism, resource tracking and auto-cleanup, error tracking, retries, repeats, ..., <strong>and </strong>a static environment.  All of which <em>could happen </em>in the <code>addRdr</code> function (because <code>mx</code> and <code>my</code> are computations) &#x2013; but the implementation doesn&apos;t care, it is abstracted away.  All it cares about is that the values are bindable and readable!  </p><blockquote>This is the path to true abstraction &#x2013; where everything is pure.  We can safely abstract, because we know all of the components are playing by the rules!</blockquote><p>You may think this kind of abstraction isn&apos;t that valuable.  But, if you remember the real-world domain-monads example from the previous article &#x2013; where I created a <code>Db</code> monad, a <code>Service</code> monad, and an <code>Api</code> monad &#x2013; then it&apos;s not a massive stretch to imagine writing some very general support functions that work with all of those monads (using the <code>Monad</code> constraint) and accessing their configuration (using the <code>Readable</code> constraint).  </p><p>For example, you could imagine a <code>User</code> value being in the environment and a <code>getLoggedInUser</code> function to access it from any monad that supports it:</p><pre><code class="language-csharp">public record User(string Id);
public record Session(User LoggedIn, DateTime LastAccess);

public static K&lt;M, Session&gt; getSession&lt;M&gt;()
    where M : ReaderM&lt;M, Session&gt; =&gt;
    ReaderM.ask&lt;M, Session&gt;();

public static K&lt;M, User&gt; getLoggedInUser&lt;M&gt;()
    where M : ReaderM&lt;M, Session&gt; =&gt;
    ReaderM.asks&lt;M, Session, User&gt;(s =&gt; s.LoggedIn);
</code></pre><p>We could expand that out to embed security roles and rights so we could do inline assertions throughout our code-base:</p><pre><code class="language-csharp">// Simple User type with list of roles it&apos;s a member of
public record User(string Id, Seq&lt;Role&gt; Memberships);

// Union type of rights
public abstract record Right; 
public record CanViewDemographic : Right;
public record CanSendInvoice : Right;

// Role with its allowed rights
public record Role(Seq&lt;Right&gt; Rights);
</code></pre><p>Next we can write the function exactly once to deal with access-rights:</p><pre><code class="language-csharp">public static K&lt;M, Unit&gt; assertHasRight&lt;M, R&gt;()
    where R : Right
    where M : Readable&lt;M, Session&gt;, Functor&lt;M&gt; =&gt;
    getLoggedInUser&lt;M&gt;().Map(
        u =&gt; u.Memberships.Exists(
            role =&gt; role.Rights.Exists(
                right =&gt; right is R))
            ? Prelude.unit
            : throw new SecurityException(&quot;Access denied&quot;));
</code></pre><p>Then at the start of an API call, for example, you could setup the <code>User</code> in a <code>Session</code> environment (pre-populating the rights and roles once per request). That <code>Session</code> can then be passed to the computation that represents the API request (via <code>Run(session)</code>) which will then automatically thread the session, user, and rights through your monadic stack.  </p><p>The (read-only) user, security rights, and roles will automatically propagate through your code.  Each monad that wants to have access to security credentials could just expose them via a <code>Readable</code> trait implementation.  </p><p>We can then write our security assertions code in any monad that supports them:</p><pre><code class="language-csharp">public static Eff&lt;Session, Unit&gt; sendInvoice() =&gt;
    from _ in assertHasRight&lt;Eff&lt;Session&gt;, CanSendInvoice&gt;()
    from r in doSendInvoice()
    select r;
</code></pre><p>Being able to write security code once and keep it tightly audited is the mark of a professional approach to software development.  So these abstractions are not just academic examples of what can be done with pure functional programming, they&apos;re very real examples of how you can make your code more robust and more secure. You&apos;ll be the auditors best friend &#x2013; although I&apos;m not sure that&apos;s a good thing!</p><h3 id="local-environments">Local environments</h3><p>Having a fixed static environment for your entire code-base is of course possible, but that will tend to expose more &apos;environment&apos; than is necessary for any subsystem. And so, it would be good if we could swap out our larger environments for something smaller on-the-fly.  This is where <code>ReaderT.local(f, ma)</code> and <code>ReaderT.with(f, ma)</code> comes in:</p><ul><li><code>local</code> maps an <code>Env</code> to an <code>Env</code> &#x2013; this allows simple mutation of the environment.  The <code>ma</code> computation is then run in that locally mutated environment.  By the end of the call the environment is reset.</li><li><code>with</code> maps an <code>Env</code> to an alternative type which can be any other value you like, but often it is derived from <code>Env</code>.  For example, you may have an <code>AppConfig</code> which contains a <code>DbConfig</code> &#x2013; it could make sense to only expose the <code>DbConfig</code> to your data-layer by mapping from <code>AppConfig -&gt; DbConfig</code>.</li></ul><blockquote>Note that <code>with</code> is not available in the <code>Readable</code> trait and so you must use <code>Reader.with</code> and <code>ReaderT.with</code> to map the environment to a different type (meaning we can&apos;t fully generalise the environment mapping).  For any type that encapsulates <code>ReaderT</code> or <code>Reader</code> it is worth adding your own equivalent of <code>with</code> to do environment mapping (if that makes sense for your type, some wrappers might have a fixed environment). This is a limitation brought about by how the higher-kinds are implemented (the <code>Env</code> is baked into the trait implementation) &#x2013; I haven&apos;t thought of an easy solution to this yet!</blockquote><h2 id="conclusion">Conclusion</h2><p>I often show (and will continue to show) the <code>IO</code> monad being the monad that is lifted into the transformer.  I&apos;m mostly doing this because it&apos;s easier to see tangible examples of what it means to compose monads with transformers.  Just remember that any monad can be lifted into <code>ReaderT</code> &#x2013; it could be a <code>Validation&lt;F, A&gt;</code> to have an environment for your validators (for example).</p><p>One other thing to note is that <code>ReaderT</code> would usually be the outermost type in the transformer stack.  This is usually because you want the inner monad(s) in the transformer stack to have access to the environment.  This isn&apos;t a rule, it&apos;s just usually the most effective position.</p><p>The <code>ReaderT</code> transformer really is the first &apos;control&apos; transformer that shows how capabilities can be &apos;bolted on&apos; to existing monads in a way that starts to break away from the relatively &apos;small thinking&apos; of optional types and other common FP topics.  Being able to carry a &#x2013; pure &#x2013; environment through your code really is the first part of building a pure architecture.  </p><p>In previous versions of language-ext we only have <code>Reader</code> which was just an environment carrying monad &#x2013; nothing else, it didn&apos;t compose with anything and that meant it was probably never used (I certainly never used it).  Now we have the ability to augment with readable traits and that is extremely powerful!</p><p>Next up will be the <code>StateT</code> transformer.  Very much like the <code>ReaderT</code> transformer except the environment can be modified.  Pure mutation?  You bet!</p><p><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-11-statet-monad-transformer/"><em>Part 11 - StateT monad transformer</em></a></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 9- monad transformers]]]></title><description><![CDATA[An introduction to monad transformers and how they can be used to 'stack' monadic behaviours to create super-monads!]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-9-monad-transformers/</link><guid isPermaLink="false">66534f1e2ac0342e8bc948f4</guid><category><![CDATA[csharp]]></category><category><![CDATA[functor]]></category><category><![CDATA[monad]]></category><category><![CDATA[language-ext]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Mon, 27 May 2024 09:34:56 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/05/monad-transformers.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/05/monad-transformers.png" alt="Higher Kinds in C# with language-ext [Part 9- monad transformers]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow this &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/">Part 8 - Monads (continued)</a></li></ul><p>In the last two episodes we covered monads: the philosophy behind them and some practical examples.  However, anyone who&apos;s used monads (either the new trait-based monads or the implementations from earlier versions of language-ext) will know that they don&apos;t compose with each other.  We get &apos;colouring&apos; of our functions and it&apos;s extremely cumbersome to use different colours together.</p><p>For example, let&apos;s create two functions that return different monadic &apos;colours&apos;:</p><pre><code class="language-csharp">static IO&lt;Seq&lt;string&gt;&gt; readAllLines(string path) =&gt;
    liftIO(env =&gt; File.ReadAllLinesAsync(path, env.Token))
        .Map(toSeq);

static Option&lt;string&gt; validatePath(string path) =&gt;
    Path.IsPathRooted(path) &amp;&amp; Path.IsPathFullyQualified(path)
        ? Some(path)
        : None;
</code></pre><p>One function returns the <code>IO&lt;A&gt;</code> monad, which represents side-effects.  The other returns an <code>Option&lt;A&gt;</code> &#x2013; the optional result monad which has a value of <code>None</code> to represent failure.</p><p>Ideally, we&apos;d like to validate our path before we try to read the lines from the file it represents.  The problem is that we can&apos;t combine monads in a single expression:</p><pre><code class="language-csharp">var computation = from p in validatePath(path)
                  from r in readAllLines(p)
                  select r;
</code></pre><p>And that&apos;s because the the <code>Bind</code> function expects to return the same monad it is chaining from:</p><pre><code class="language-csharp">K&lt;M, B&gt; Bind&lt;A, B&gt;(K&lt;M, A&gt; ma, Func&lt;A, K&lt;M, B&gt;&gt; f);
  ^                  ^                   ^
  |                  |                   | 
  +------------------+-------------------+</code></pre><p>Because, all of the <code>K</code> types have the same <code>M</code> baked in, we are unable to switch monadic types mid-expression.  Well, technically we are able to, but not generally &#x2013; i.e. the trait doesn&apos;t allow it, but we could write bespoke implementations for complimentary monads. </p><p>We&apos;re specifically talking about the generalisation of monads here though and they only compose with themselves, not other monadic types.  So, if we take that as a given, what do we do about it?</p><p>Well, one technique is to nest the regular monadic types.  Instead of working with <code>IO&lt;A&gt;</code> or <code>Option&lt;A&gt;</code> we could work with <code>IO&lt;Option&lt;A&gt;&gt;</code>:</p><pre><code class="language-csharp">var computation = from op in IO.pure(validatePath(path))
                  from r  in op.Match(Some: readAllLines,
                                      None: () =&gt; IO.Fail&lt;Seq&lt;string&gt;&gt;(Errors.None))   
                  select r;
</code></pre><p>By lifting the <code>Option</code> returning <code>validatePath</code> into the <code>IO</code> monad we get a <code>IO&lt;Option&lt;string&gt;&gt;</code>, but that just means <code>op</code> is a <code>Option&lt;string&gt;</code> and it all gets very messy, very quickly &#x2013; we&apos;re effectively manually implementing the bind function for <code>Option</code>.  It compiles and runs though!  So, that hints at a possible approach if we can encapsulate that nested monadic type behaviour.</p><p><em>This is where monad transformers come in!</em></p><p>Monad transformers allow &apos;stacking&apos; of different monad types into <em>&apos;super monads&apos;</em> that aggregate all of the features of the stacked elements.</p><blockquote>What follows will be quite hard going if you&apos;re new to monads or monad transformers.  So, I&apos;ll give you a sneak preview of where we&apos;re going to be at the end of this article.  Hopefully you won&apos;t lose the will to live halfway through!</blockquote><p><em>By the end of this article you&apos;ll be able to compose monads into monad transformer stacks.  These compositions aggregate all of the abilities of each monad &apos;colour&apos; into one type.  </em></p><p>The example above &#x2013;  of trying to mix <code>IO&lt;A&gt;</code> and <code>Option&lt;A&gt;</code> &#x2013; can be achieved (in language-ext) using the <code>OptionT&lt;IO, A&gt;</code> monad transformer stack.  It lifts the regular <code>IO</code> monad into the <code>OptionT</code> monad transformer which creates a new monad that is the sum of its parts.</p><p>The functions <code>readAllLines</code> and <code>validatePath</code> can stay <em>exactly as they are above</em>.  We just need to update the LINQ expression:</p><pre><code class="language-csharp">var computation = from p in OptionT.lift(validatePath(path))
                  from r in readAllLines(path)
                  select r;

var result = computation.Run(); // Option&lt;Seq&lt;string&gt;
</code></pre><p>The reason <code>readAllLines</code> doesn&apos;t need lifting is because it returns the <code>IO</code> monad and the <code>OptionT</code> monad-transformer supports <code>liftIO</code> &#x2013; which allows any IO computation to be lifted into a monad-transformer stack of any depth as long as it has the <code>IO</code> monad at the bottom of the stack (and because there are special <code>SelectMany</code> extensions for doing this <code>liftIO</code> work). </p><p>If you wanted to be completely explicit about it, you could write the <code>readAllLines(path)</code> expression as:</p><pre><code class="language-csharp">MonadIO.liftIO&lt;OptionT&lt;IO&gt;, Seq&lt;string&gt;&gt;(readAllLines(path))</code></pre><p>Obviously there&apos;s more overhead to writing that! But, that&apos;s what <code>Bind</code> and <code>SelectMany</code> do automatically for you when using <code>IO</code> based monads in a LINQ expression.</p><blockquote>What we have just done by using <code>OptionT&lt;IO, A&gt;</code> is recreate <code>OptionAsync&lt;A&gt;</code> (now removed from language-ext) without writing any new code. We could also use <code>OptionT&lt;Eff, A&gt;</code> to have a more advanced version with proper error handling, or <code>ValidationT&lt;IO, A&gt;</code> if we wanted IO and validation... this is a very powerful!</blockquote><p>OK, hopefully you&apos;ve seen enough to make you want to read on, so let&apos;s take a look at the monad-transformer trait: <code>MonadT&lt;T, M&gt;</code></p><pre><code class="language-csharp">public interface MonadT&lt;T, out M&gt; : Monad&lt;T&gt; 
    where T : MonadT&lt;T, M&gt;
    where M : Monad&lt;M&gt;
{
    public static abstract K&lt;T, A&gt; Lift&lt;A&gt;(K&lt;M, A&gt; ma);
}
</code></pre><p>Notice the constraints on <code>T</code> and <code>M</code>:</p><ul><li><code>T</code> is constrained to be itself like all traits.  <em>Itself </em>is also a <code>Monad&lt;T&gt;</code></li><li><code>M</code> is constrained to be a <code>Monad&lt;M&gt;</code></li></ul><p>We inherit <code>Monad&lt;T&gt;</code> which means the eventual trait implementation is both a monad-transformer <strong><em>and </em></strong>a monad.  This is important when stacking monad-transformers, because a monad-transformer is also just a monad that can be stacked inside other monad-transformers.</p><p>So, <code>T</code> is considered the &apos;outer&apos; monad and <code>M</code> is the &apos;inner&apos; monad.  If C# had first-class support for higher-kinds the type would be: <code>T&lt;M&lt;A&gt;&gt;</code> &#x2013; but in our world we&apos;re working with the following type: <code>K&lt;T, K&lt;M, A&gt;&gt;</code></p><p>The single function that the trait supports is <code>Lift</code> &#x2013; for lifting an inner monad into an outer monad transformer.</p><p>The important thing to note is that you don&apos;t get to make a regular monad into a monad-transformer.  You have to write a bespoke monad-transformer type.  However, you <em>can</em> create any regular monad from a monad-transformer by lifting the <code>Identity</code> monad into the transformer. </p><p>What that means is you can create <code>Reader&lt;Env, A&gt;</code> from <code>ReaderT&lt;Env, Identity, A&gt;</code> and <code>Option&lt;A&gt;</code> from <code>OptionT&lt;Identity, A&gt;</code>, etc.  Practically though, that isn&apos;t always how it&apos;s done, mostly for performance reasons.  But it&apos;s good to know that any regular monad can be made by composing its transformer and <code>Identity</code>.  </p><blockquote>Our next example will <em>go</em> <em>the other way </em>by creating a transformer from its monad.</blockquote><p>By convention anything relating to transformers (or nested types) in language-ext has a <code>T</code> suffix.  So, if we want to make a transformer version of the <code>Maybe&lt;A&gt;</code> type, from the last article, then we&apos;d create a new type called <code>MaybeT&lt;M, A&gt;</code> &#x2013; the transformer provides the standard optional behaviour of <code>Maybe</code> but augments it with the <code>M</code> monad that is lifted into it.</p><pre><code class="language-csharp">public record MaybeT&lt;M, A&gt;(K&lt;M, Maybe&lt;A&gt;&gt; runMaybeT) : K&lt;MaybeT&lt;M&gt;, A&gt;
    where M : Monad&lt;M&gt;
{
    // members to come...
}

public static class MaybeTExtensions
{
    // Standard downcast but with Monad constraint on M
    public static MaybeT&lt;M, A&gt; As&lt;M, A&gt;(this K&lt;MaybeT&lt;M&gt;, A&gt; ma) 
        where M : Monad&lt;M&gt; =&gt;
        (MaybeT&lt;M, A&gt;)ma;
}
</code></pre><p>This is our starting point for <code>MaybeT</code>.  Note how the <code>runMaybeT</code> member is a nested monad.  We only know the type of one of the monads, the <code>Maybe&lt;A&gt;</code> &#x2013; but that&apos;s enough &#x2013; we know how <code>Maybe&lt;A&gt;</code> works, so we can &apos;see inside&apos; whereas <code>M</code> is opaque and we must rely on only what we know about it: it&apos;s a <code>Functor</code>, <code>Applicative</code>, and a <code>Monad</code>.  So, we can access its <code>Map</code>, <code>Pure</code>, and <code>Bind</code> functions.</p><blockquote>NOTE: The nesting order isn&apos;t fixed.  Sometimes the &apos;known&apos; monad is the inner monad and sometimes its the outer monad.  So, just be aware that stacking transformers can sometimes be a little bit confusing.</blockquote><p>Now, let&apos;s start creating the <code>MaybeT&lt;M&gt;</code> trait implementation:</p><pre><code class="language-csharp">public class MaybeT&lt;M&gt; : 
    MonadT&lt;MaybeT&lt;M&gt;, M&gt;, 
    MonadIO&lt;MaybeT&lt;M&gt;&gt;
    where M : Monad&lt;M&gt;
{
   // to be filled in !!
}
</code></pre><p>This works the same way to all our other HKT traits, just this time we&apos;re working with the  <code>MonadT</code> trait.  <code>MonadT</code> has its own method (<code>Lift</code>) but it also inherits: <code>Monad</code>, <code>Applicative</code>, and <code>Functor</code> so we have to implement them all!</p><blockquote>We are also inheriting <code>MonadIO</code>.  <code>MonadIO</code> is a special-case trait that needs some serious explanation, which I&apos;ll do a little later.  Just for now, make sure you inherit <code>MonadIO</code> on any transformer type you make, unless you very specifically want it to not support composition with IO types.</blockquote><p>First, <code>Functor</code>:</p><pre><code class="language-csharp">public partial class MaybeT&lt;M&gt; : MonadT&lt;MaybeT&lt;M&gt;, M&gt;
    MonadT&lt;MaybeT&lt;M&gt;, M&gt;, 
    MonadIO&lt;MaybeT&lt;M&gt;&gt;
    where M : Monad&lt;M&gt;
{
    static K&lt;MaybeT&lt;M&gt;, B&gt; Functor&lt;MaybeT&lt;M&gt;&gt;.Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;MaybeT&lt;M&gt;, A&gt; ma) =&gt;
        new MaybeT&lt;M, B&gt;(
            ma.As()
              .runMaybeT
              .Map(mx =&gt; mx.Map(f).As()));

    // to be filled in !!
}</code></pre><p>If you look closely at the implementation you&apos;ll notice it has two nested calls to <code>Map</code>.  We get the <code>runMaybeT</code> property from the transformer (which is two nested monads), we call <code>Map</code> on it, which makes the inner monad available to us (<code>mx</code>) &#x2013; we then call <code>Map</code> on <code>mx</code> with the <code>f</code> function to do the actual mapping.  The two <code>Map</code> functions will automatically re-wrap the values in their nested monads, leaving us with a <code>K&lt;M, Maybe&lt;B&gt;&gt;</code> which we can use to construct a new <code>MaybeT&lt;M, B&gt;</code>.</p><p>You should start to see what we&apos;re doing here: we&apos;re unwrapping the layers of the two nested containers (<code>M</code> and <code>Maybe</code>) so that we can work on the values contained within.  </p><p>What&apos;s most important here is that we&apos;re using <code>Map</code> from <code>M</code> and <code>Map</code> from <code>Maybe</code>, which means we&apos;re using their inbuilt behaviours &#x2013; one of which we know is to give optional results, but the other totally depends on the implementation of <code>M</code>.</p><p>Next, <code>Applicative</code>:</p><pre><code class="language-csharp">static K&lt;MaybeT&lt;M&gt;, A&gt; Applicative&lt;MaybeT&lt;M&gt;&gt;.Pure&lt;A&gt;(A value) =&gt;
    new MaybeT&lt;M, A&gt;(M.Pure(Maybe.Just(value)));

static K&lt;MaybeT&lt;M&gt;, B&gt; Applicative&lt;MaybeT&lt;M&gt;&gt;.Apply&lt;A, B&gt;(K&lt;MaybeT&lt;M&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;MaybeT&lt;M&gt;, A&gt; ma) =&gt; 
    mf.As().Bind(f =&gt; ma.As().Map(f));
</code></pre><p><code>Pure</code> is the most interesting implementation.  We use the outer monad&apos;s <code>Pure</code> function to lift the <code>Maybe</code> into it.  This gives us the nested <code>K&lt;M, Maybe&lt;A&gt;&gt;</code>.</p><p>We&apos;re seeing that monad-transformers aren&apos;t particularly special when you <em>look inside</em> they&apos;re just doing the same work I did in the very first example where I manually matched on the <code>Option</code> so I could use it with the <code>IO</code> monad.  The monad-transformer merely encapsulates that messiness. The result will be a new monad that has captured the complexity of working with two nested types and captures the two distinct monad <em>effects</em>.</p><p>By the way, I&apos;ve left the <code>Apply</code> function to a default that uses <code>Bind</code> and <code>Map</code> &#x2013; there are avenues for more specific applicative behaviour, but not with this type.  Why? Because the way the types are nested in a transformer means we can only really run <code>Apply</code> on the inner-types.  For example, take a look at a more complete implementation for <code>MaybeT</code>:</p><pre><code class="language-csharp">new MaybeT&lt;M, B&gt;(mf.As().runMaybeT.Bind(maybeF =&gt; ma.As().runMaybeT.Map(maybeA =&gt; maybeF.Apply(maybeA))));</code></pre><p>As you can see, we need to run <code>Bind</code> and <code>Map</code> on the outer-types so that we can get access to the inner <code>Maybe</code> values before then calling <code>Apply</code> on them.  So, only the inner-types have their applicative behaviour invoked and because the inner-type is a <code>Maybe</code>, which doesn&apos;t have any interesting applicative behaviour &#x2013; like say <code>Validation</code> &#x2013; we instead use a simpler implementation that only uses <code>Bind</code> and <code>Map</code>.</p><p>Now, <code>Monad</code>:</p><pre><code class="language-csharp">static K&lt;MaybeT&lt;M&gt;, B&gt; Monad&lt;MaybeT&lt;M&gt;&gt;.Bind&lt;A, B&gt;(K&lt;MaybeT&lt;M&gt;, A&gt; ma, Func&lt;A, K&lt;MaybeT&lt;M&gt;, B&gt;&gt; f) =&gt;
    new MaybeT&lt;M, B&gt;(
        ma.As().runMaybeT.Bind(mx =&gt;
            mx switch
            {
                Just&lt;A&gt; (var x) =&gt; f(x).As().runMaybeT,
                Nothing&lt;A&gt;      =&gt; M.Pure(Maybe.Nothing&lt;B&gt;())
            }));</code></pre><p>This is a little bit more complex.  The reason for the complexity is that the <code>f</code> argument returns a <code>MaybeT&lt;M, B&gt;</code> &#x2013; this is problematic, because it&apos;s the outer-outer wrapper and we&apos;re unwrapping our monadic types to get at the <code>A</code> value to pass to <code>f</code>.  The last thing we need when we&apos;re in the middle of the tree rings is to have some bark returned!</p><p>This is where our knowledge of the inner <code>Maybe</code> monad comes in useful.  Because, not only do we know that it&apos;s a monad, but we know we can pattern-match on it and just make it evaporate! </p><p>So, we run <code>Bind</code> on the outer monad, it unwraps the inner monad (which is a <code>Maybe&lt;A&gt;</code>), we then pattern-match on the <code>Maybe&lt;A&gt;</code>, if the result is a <code>Just&lt;A&gt;</code> we get the <code>A</code> value and pass it to the bind function: <code>f</code> - which returns a <code>MaybeT&lt;M, A&gt;</code>.  We know that <code>MaybeT&lt;M, A&gt;</code> has a property which is a <code>K&lt;M, ...&gt;</code> type and that&apos;s what the bind function wants in return!  If the result is <code>Nothing</code> then we can lift a new <code>Nothing&lt;B&gt;</code> into the <code>M</code> monad using <code>M.Pure</code> &#x2013; which also satisfies the <code>Bind</code> requirements.</p><blockquote>Phew!</blockquote><p>You might want to read and re-read that a number of times to really grok what&apos;s happening here.  But the crux of it is that we&apos;re nesting the bind behaviours of each monad: <code>M</code> and <code>Maybe</code>.  So, the result is a new type, <code>MaybeT</code>, which has optional behaviour <em>and</em> <code>M</code> behaviour &#x2013; <em>whatever that is!</em></p><p>We&apos;re not done yet.  We still need to implement the <code>MonadT</code> interface:</p><pre><code class="language-csharp">static K&lt;MaybeT&lt;M&gt;, A&gt; MonadT&lt;MaybeT&lt;M&gt;, M&gt;.Lift&lt;A&gt;(K&lt;M, A&gt; ma) =&gt;
    new MaybeT&lt;M, A&gt;(ma.Map(Maybe.Just));</code></pre><p>That&apos;s it! So, although it took a fair amount of work to make the transformer into a valid monad, applicative, and functor; the actual work of making a monad transformer is simply lifting a generic monad type &apos;into&apos; it.</p><p><code>Lift</code> lets us take a monad <code>M</code> and <em>lift it into the transformer</em>.  Because we&apos;re using <code>M</code> as the outer monad we need to call <code>Map</code> on it and map the <code>A</code> to a <code>Maybe&lt;A&gt;</code>.  This creates the nested type we need.</p><p>OK, so that&apos;s everything from the <code>MonadT</code> trait implemented.  It is usable as-is, but any transformer you implement will always benefit from some convenience functions.  The functions will depend entirely on the transformer, just as it does with any other monad.</p><p>So, for <code>MaybeT</code> we might add:</p><pre><code class="language-csharp">public partial class MaybeT&lt;M&gt;
{
    public static MaybeT&lt;M, A&gt; lift&lt;A&gt;(Maybe&lt;A&gt; ma) =&gt;
        new(M.Pure(ma));

    public static MaybeT&lt;M, A&gt; Just&lt;A&gt;(A value) =&gt;
        lift(Maybe.Just(value));

    public static MaybeT&lt;M, A&gt; Nothing&lt;A&gt;() =&gt;
        lift(Maybe.Nothing&lt;A&gt;());
}
</code></pre><p>As well as:</p><pre><code class="language-csharp">public class MaybeT
{
    public static MaybeT&lt;M, A&gt; lift&lt;M, A&gt;(K&lt;M, A&gt; ma)
        where M : Monad&lt;M&gt; =&gt;
        new (ma.Map(Maybe.Just));
}
</code></pre><p>Those will give us the ability to lift either an <code>M&lt;A&gt;</code> or a <code>Maybe&lt;A&gt;</code> into the transformer as well as to construct a <code>Just</code> or <code>Nothing</code> state transformer.</p><blockquote>Lifting can be done with the generic <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Monads/MonadT/MonadT.Trait.cs?ref=paullouth.com"><code>MonadT.lift(...)</code> function</a>.  So, technically you don&apos;t need to implement lift functions.  But, I find it&apos;s often easier to create some bespoke lifting functions as it often requires fewer generic arguments.</blockquote><p>Let&apos;s go back to our example from the start of this article and rework the <code>readAllLines</code> and <code>validatePath</code> functions:</p><pre><code class="language-csharp">static MaybeT&lt;IO, Seq&lt;string&gt;&gt; readAllLines(string path) =&gt;
    MaybeT.lift(
        liftIO(async env =&gt; await File.ReadAllLinesAsync(path, env.Token))
            .Map(toSeq));

static MaybeT&lt;IO, string&gt; validatePath(string path) =&gt;
    Path.IsPathRooted(path) &amp;&amp; Path.IsPathFullyQualified(path)
        ? MaybeT&lt;IO&gt;.Just(path)
        : MaybeT&lt;IO&gt;.Nothing&lt;string&gt;();</code></pre><p>You can see now that we&apos;re returning a common type for both.  We have lifted the <code>IO</code> monad into the <code>MaybeT</code> transformer: giving the IO monad optional behaviour.  </p><ul><li>In <code>readAllLines</code> we&apos;re calling <code>MaybeT.lift</code> to lift the <code>IO</code> into the transformer</li><li>In <code>validatePath</code> we&apos;re using the new <code>MaybeT.Just</code> and <code>MaybeT.Nothing</code> functions.</li></ul><p>This gives us a common type that we know will work together in monad-bind expressions.  So, we can now use them together in a LINQ expression:</p><pre><code class="language-csharp">var computation = from p in validatePath(path)
                  from r in readAllLines(path)
                  select r;
</code></pre><p>The other approach is to leave the functions as they are ...</p><pre><code class="language-csharp">static IO&lt;Seq&lt;string&gt;&gt; readAllLines(string path) =&gt;
    liftIO(async env =&gt; await File.ReadAllLinesAsync(path, env.Token))
        .Map(toSeq);

static Maybe&lt;string&gt; validatePath(string path) =&gt;
    Path.IsPathRooted(path) &amp;&amp; Path.IsPathFullyQualified(path)
        ? Maybe.Just(path)
        : Maybe.Nothing&lt;string&gt;();
</code></pre><p>... and lift them ad-hoc:</p><pre><code class="language-csharp">var computation = from p in MaybeT&lt;IO&gt;.lift(validatePath(path))
                  from r in MaybeT.lift(readAllLines(path))
                  select r;</code></pre><h2 id="io">IO</h2><p>Because lifting the <code>IO&lt;A&gt;</code> monad into a transformer-stack is so common there&apos;s some special functionality that makes this easy.  In Haskell there&apos;s a trait called <code>MonadIO</code> that gives the type implementing it a function called <code>liftIO</code>.</p><blockquote>There is no transformer version of <code>IO&lt;A&gt;</code>, it is expected that it will <em>always </em>be the innermost monad in any, IO based, transformer stack and therefore can&apos;t ever be a transformer itself.  </blockquote><p>Because, you may have a number of transformers in your stack, calling <code>lift(lift(lift(io)))</code> is an inconvenience.  So, <code>liftIO</code> does that work for you. It does this by calling <code>M.LiftIO</code> for the transformed monad <code>M</code>.  <code>M</code> may also be a transformer and so it will call its <code>M.LiftIO</code>, etc. this continues until the innermost monad of the transformer stack is reached, which should be an <code>IO&lt;A&gt;</code> monad.  To do this we need a new trait called <code>MonadIO</code> that has a <code>LiftIO</code> method.</p><p>We can&apos;t however create a general <code>MonadIO</code> <em>trait</em> in C#.  The problem is that we don&apos;t have <em>ad-hoc</em> traits... each higher-kinded type we implement has a single trait-implementation class, which means your type either <em>always</em> supports <code>IO</code> or it <em>never</em> does.  So, if you create a transformer type like <code>MaybeT</code> then you either enable <code>liftIO</code> for <code>MaybeT&lt;IO, A&gt;</code> <em>and </em><code>MaybeT&lt;Identity, A&gt;</code> or for none of them.  Clearly, in the second example with <code>Identity</code> there isn&apos;t an <code>IO</code> monad in the stack, so which option do we pick?</p><p>To get around this <code>Monad&lt;M&gt;</code> inherits a &apos;partial interface&apos;, called <code>Maybe.MonadIO&lt;A&gt;</code>: </p><pre><code class="language-csharp">public static class Maybe
{
    public interface MonadIO&lt;M&gt;
        where M : MonadIO&lt;M&gt;, Monad&lt;M&gt;
    {
        public static virtual K&lt;M, A&gt; LiftIO&lt;A&gt;(K&lt;IO, A&gt; ma) =&gt;
            M.LiftIO(ma.As());

        public static virtual K&lt;M, A&gt; LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
            throw new ExceptionalException(Errors.LiftIONotSupported);

        public static virtual K&lt;M, IO&lt;A&gt;&gt; ToIO&lt;A&gt;(K&lt;M, A&gt; ma) =&gt;
            throw new ExceptionalException(Errors.ToIONotSupported);

        public static virtual K&lt;M, B&gt; MapIO&lt;A, B&gt;(K&lt;M, A&gt; ma, Func&lt;IO&lt;A&gt;, IO&lt;B&gt;&gt; f) =&gt;
            M.ToIO(ma).Bind(io =&gt; M.LiftIO(f(io)));
    }
}</code></pre><p>These are the minimum set of methods that are needed to support IO operations and especially the stacking of transformers and monads in such a way that the <code>IO&lt;A&gt;</code> monad is sitting at the innermost stack position.  The type is called <code>Maybe.MonadIO</code> to indicate that maybe the <code>IO</code> behaviours have been implemented, but also, maybe not.  This isn&apos;t ideal, but at least it&apos;s clear that it&apos;s unsure!</p><p>Overriding and implementing <code>LiftIO</code> and <code>ToIO</code> gives IO functionality to your stack.  And so, in theory that&apos;s all we need to implement.</p><p>However, on top of that, we want to be able to mark functions, classes, etc. as constrained to need IO.  For example, this shows that the <code>readAllBytes</code> function works with monads that are constrained to support IO:</p><pre><code class="language-csharp">public static K&lt;M, Seq&lt;byte&gt;&gt; readAllBytes&lt;M&gt;(string path) 
    where M : MonadIO&lt;M&gt; =&gt;
    ...;</code></pre><p>We can&apos;t really do this effectively if all <code>Monad&lt;M&gt;</code> types inherit <code>Maybe.MonadIO&lt;M&gt;</code>.  <code>where M : Maybe.MonadIO&lt;M&gt;</code> will be true for <em>all </em>monad or monad-transformers, regardless of whether they implemented <code>LiftIO</code> and <code>ToIO</code> or not.</p><p><em>So, we have </em><a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Monads/MonadIO/MonadIO.Trait.cs?ref=paullouth.com"><em>a second <code>MonadIO&lt;M&gt;</code> trait</em></a><em>, which is not nested inside a <code>Maybe</code> type, that is the real &apos;this type definitely supports IO&apos; declaration.  </em></p><p>The <code>IO&lt;A&gt;</code> type derives from <code>MonadIO&lt;IO&gt;</code>, the <code>Eff&lt;A&gt;</code> type derives from <code>MonadIO&lt;Eff&gt;</code>, as expected, because they both are IO side-effects types.  But also, every transformer type inherits <code>MonadIO&lt;T&gt;</code> because they support the &apos;pass along&apos; process of calling the <code>Maybe.MonadIO</code> behaviours of the type they have lifted (the <code>M</code> in <code>MonadT&lt;T, M&gt;</code>).</p><p>This all sounds crazily complicated, I realise, but it effectively allows for  us to create IO implementations and constraints that work generally for monads, but also work optionally for monad-transformers. Just remember that monad-transformers should almost always implement <code>MonadIO&lt;T&gt;</code> &#x2013; the only reason not to is if you very specifically want to bar IO from a stack (which is rare, but also valid).</p><p>Let&apos;s now discuss the interface itself:</p><p><code>LiftIO</code> is a function in the <code>Maybe.Monad&lt;M&gt;</code> trait that has a default implementation which throws an exception.  </p><p>This is the default implementation:</p><pre><code class="language-csharp">public static virtual K&lt;M, A&gt; LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
    throw new ExceptionalException(Errors.IONotInTransformerStack);
</code></pre><p>If we implement that for our <code>MaybeT</code> transformer then we&apos;ll get <code>liftIO</code> support:</p><pre><code class="language-csharp">static K&lt;MaybeT&lt;M&gt;, A&gt; Maybe.Monad&lt;MaybeT&lt;M&gt;&gt;.LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
    new MaybeT&lt;M, A&gt;(M.LiftIO(ma.Map(Maybe.Just)));
</code></pre><p>It takes an <code>IO&lt;A&gt;</code> to lift.  First we map the result of the <code>IO&lt;A&gt;</code> to <code>IO&lt;Maybe&lt;A&gt;&gt;</code>.  And then we <em>pass it along</em> to the <code>M</code> monad &#x2013; which, if it&apos;s not the <code>IO</code> monad, will also pass it along... this will continue until it reaches the <code>IO</code> monad in the stack. </p><p>The IO monad can then just return the <code>IO&lt;A&gt;</code> because it <em>is </em>the IO monad!</p><pre><code class="language-csharp">static K&lt;IO, A&gt; Maybe.Monad&lt;IO&gt;.LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt; 
    ma;
</code></pre><p>And so, this &apos;opens up&apos; the stack, injects the IO monad into it and then returns a newly constructed stack.  Very cool.</p><p>Let&apos;s update our earlier example:</p><pre><code class="language-csharp">static IO&lt;Unit&gt; writeAllLines(string path, Seq&lt;string&gt; lines) =&gt;
    liftIO(async env =&gt; await File.WriteAllLinesAsync(path, lines, env.Token));

static IO&lt;Seq&lt;string&gt;&gt; readAllLines(string path) =&gt;
    liftIO(async env =&gt; await File.ReadAllLinesAsync(path, env.Token))
        .Map(toSeq);

static MaybeT&lt;IO, string&gt; validatePath(string path) =&gt;
    Path.IsPathRooted(path) &amp;&amp; Path.IsPathFullyQualified(path)
        ? MaybeT&lt;IO&gt;.Just(path)
        : MaybeT&lt;IO&gt;.Nothing&lt;string&gt;();</code></pre><p>I&apos;ve now got two <code>IO</code> functions and one <code>MaybeT&lt;IO, string&gt;</code> function:</p><p>We can now write the LINQ expression without manually lifting any of the IO functions:</p><pre><code class="language-csharp">var computation = from p in validatePath(path)
                  from l in readAllLines(path)
                  from _ in writeAllLines(path, l)
                  select unit;
</code></pre><p>Which is very elegant.</p><p>The reason this works (with different monadic types in the same expression) is because there are bespoke extension-methods for <code>Bind</code> and <code>SelectMany</code> that know how to work with the <code>IO</code> monad:</p><pre><code class="language-csharp">public static K&lt;M, B&gt; Bind&lt;M, A, B&gt;(
    this K&lt;M, A&gt; ma,
    Func&lt;A, K&lt;IO, B&gt;&gt; f)
    where M : MonadIO&lt;M&gt; =&gt;
    M.Bind(ma, x =&gt; M.LiftIO(f(x).As()));</code></pre><p>You can see the call to <code>LiftIO</code> that makes the <code>IO&lt;B&gt;</code> into a <code>K&lt;M, B&gt;</code> (as long as <code>M</code> has implemented <code>LiftIO</code>).</p><p>So, the <code>IO</code> monad is <em>the </em>monad that does IO.  It might seem obvious, but if you&apos;re building anything else that does IO then you want the <code>IO&lt;A&gt;</code> monad internally.</p><h2 id="invoking-the-transformer">Invoking the transformer</h2><p>OK, that&apos;s all great, how do we run these things? </p><p>Ultimately, it depends on the transformer, some of them you&apos;ll be able to &apos;realise&apos; an underlying concrete value, others not.  But a good convention is to add a <code>Run</code> extension to extract the underlying monad-stack:</p><pre><code class="language-csharp">public static K&lt;M, Maybe&lt;A&gt;&gt; Run&lt;M, A&gt;(this K&lt;MaybeT&lt;M&gt;, A&gt; ma) 
    where M : Monad&lt;M&gt; =&gt;
    ma.As().runMaybeT;</code></pre><p>In that abstract form it&apos;s not that useful, but when it&apos;s used concretely then the consumer of the transformer can work with the stack:</p><pre><code class="language-csharp">var computation = from p in validatePath(path)
                  from l in readAllLines(path)
                  from _ in writeAllLines(path, l)
                  select unit;

var result = computation.Run().Run(); // Maybe&lt;Seq&lt;string&gt;</code></pre><p>So, above, we <code>Run</code> the transformer, we get a <code>K&lt;IO, Maybe&lt;Seq&lt;string&gt;&gt;</code> in return, we then <code>Run</code> that and that gets us a <code>Maybe&lt;Seq&lt;string&gt;&gt;</code>.  These are now concrete results we can work with.</p><p>An important point to note is that because you&apos;re manually unwrapping each layer of the transformer stack: you can stop at any point.  So, partially unwrapping might make sense depending on the circumstances and what other monadic expressions you&apos;re working in.</p><h2 id="there-must-be-an-easier-way">There must be an easier way?!</h2><p>Creating new monad transformers is, for sure, quite a bit of effort.  But the benefit of using language-ext is that I have written most of the transformers you need.  And so, really you only need to compose them yourself.  </p><p>That doesn&apos;t necessarily mean composing them is trivial.  In other languages with monad-transformers they&apos;re also quite awkward to work with.  </p><p>Mostly you&apos;ll want to wrap your transformer-stack into a new type that hides the stack, but exposes the functionality through a bespoke API.  The benefit of taking this approach is that you can change the stack at a later stage without the rest of your code breaking, but also it just reduces the amount of typing of generics.</p><p>A good example of this is <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Effects/Eff/Eff%20with%20runtime/Eff.cs?ref=paullouth.com">the <code>Eff&lt;RT, A&gt;</code> type in language-ext</a>.  It has been rewritten to use monad-transformers.  It stacks the <code>ReaderT</code> transformer with <code>IO</code>:</p><pre><code class="language-csharp">public record Eff&lt;RT, A&gt;(ReaderT&lt;RT, IO, A&gt; effect) : K&lt;Eff&lt;RT&gt;, A&gt;
{
   ...
}
</code></pre><blockquote>There&apos;s a lot of code in the <code>Eff</code> monad.  That&apos;s not a requirement of using transformers, it&apos;s just a natural artefact of the evolution of the <code>Eff</code> monad from previous versions of language-ext.  It is however worth looking at how the <code>Eff</code> type leans heavily on the inbuilt behaviours of <code>ReaderT</code> and <code>IO</code>.</blockquote><p>At the time of writing the following monad-transformers are in language-ext:</p><ul><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/Alternative%20Monads/EitherT/index.html?ref=paullouth.com"><code>EitherT&lt;L, M, R&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/Alternative%20Monads/OptionT/index.html?ref=paullouth.com"><code>OptionT&lt;M, R&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/Alternative%20Monads/TryT/index.html?ref=paullouth.com"><code>TryT&lt;M, R&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/Alternative%20Monads/ValidationT/index.html?ref=paullouth.com"><code>ValidationT&lt;F, M, R&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/ContT/index.html?ref=paullouth.com"><code>ContT&lt;R, M, A&gt;</code></a> &#x2013; exists but still WIP</li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/IdentityT/index.html?ref=paullouth.com"><code>IdentityT&lt;M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/Reader/ReaderT/index.html?ref=paullouth.com"><code>ReaderT&lt;E, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/Writer/WriterT/index.html?ref=paullouth.com"><code>WriterT&lt;W, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/State/StateT/index.html?ref=paullouth.com"><code>StateT&lt;S, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Core/Monads/State%20and%20Environment%20Monads/RWS/RWST/index.html?ref=paullouth.com"><code>RWST&lt;R, W, S, M, A&gt;</code> </a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/Pipes/ProducerT/?ref=paullouth.com"><code>ProducerT&lt;OUT, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/SinkT/?ref=paullouth.com"></a><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/Pipes/PipeT/?ref=paullouth.com"><code>PipeT&lt;IN, OUT, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/Pipes/ConsumerT/?ref=paullouth.com"><code>ConsumerT&lt;IN, M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/SinkT/?ref=paullouth.com"><code>SinkT&lt;M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/SourceT/?ref=paullouth.com"><code>SourceT&lt;M, A&gt;</code></a></li><li><a href="https://louthy.github.io/language-ext/LanguageExt.Streaming/ConduitT/?ref=paullouth.com"><code>ConduitT&lt;M, A, B&gt;</code></a></li></ul><p>By combining these transformers with other monads you can create extremely complex functionality.</p><h2 id="deriving">Deriving</h2><p>When we wrap existing monad-transformer stacks in a new type our trait-implementation class ends up being a mechanical wrapping of the lifted transformer type.</p><p>So, for example, let&apos;s create a simple <code>App</code> monad that wraps a readable/IO monad-transformer stack:</p><pre><code class="language-csharp">// Simple record for carrying application configuration
public record AppConfig;

// Application monad that wraps a monad-transformer stack
public record App&lt;A&gt;(ReaderT&lt;AppConfig, IO, A&gt; runService) : K&lt;App, A&gt;;
</code></pre><blockquote>This encapsulates the <code>IO</code> and configuration passing.</blockquote><p>Then we can add our extensions for downcasting and running:</p><pre><code class="language-csharp">// Extensions for downcasting and running
public static class AppExtensions
{
    public static App&lt;A&gt; As&lt;A&gt;(this K&lt;App, A&gt; ma) =&gt;
        (App&lt;A&gt;)ma;

    public static IO&lt;A&gt; Run&lt;A&gt;(this K&lt;App, A&gt; ma, AppConfig config) =&gt;
        ma.As().runService.Run(config).As();
}
</code></pre><p>Now we need the trait-implementations:</p><pre><code class="language-csharp">// Trait implementation class
public class App : 
    MonadIO&lt;App&gt;, 
    Readable&lt;App, AppConfig&gt;
{
    public static K&lt;App, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;App, A&gt; ma) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, A&gt; Pure&lt;A&gt;(A value) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, B&gt; Apply&lt;A, B&gt;(K&lt;App, Func&lt;A, B&gt;&gt; mf, K&lt;App, A&gt; ma) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, B&gt; Bind&lt;A, B&gt;(K&lt;App, A&gt; ma, Func&lt;A, K&lt;App, B&gt;&gt; f) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, A&gt; LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, IO&lt;A&gt;&gt; ToIO&lt;A&gt;(K&lt;App, A&gt; ma) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, A&gt; Asks&lt;A&gt;(Func&lt;AppConfig, A&gt; f) =&gt;
        throw new NotImplementedException();

    public static K&lt;App, A&gt; Local&lt;A&gt;(Func&lt;AppConfig, AppConfig&gt; f, K&lt;App, A&gt; ma) =&gt;
        throw new NotImplementedException();
}</code></pre><p>That&apos;s quite a lot for us to fill in, but let&apos;s do it ...</p><pre><code class="language-csharp">// Trait implementation class
public class App : 
    MonadIO&lt;App&gt;, 
    Readable&lt;App, AppConfig&gt;
{
    public static K&lt;App, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;App, A&gt; ma) =&gt;
        new App&lt;B&gt;(ma.As().runService.Map(f));

    public static K&lt;App, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new App&lt;A&gt;(ReaderT.pure&lt;AppConfig, IO, A&gt;(value));

    public static K&lt;App, B&gt; Apply&lt;A, B&gt;(K&lt;App, Func&lt;A, B&gt;&gt; mf, K&lt;App, A&gt; ma) =&gt;
        new App&lt;B&gt;(mf.As().runService.Apply(ma.As().runService));

    public static K&lt;App, B&gt; Bind&lt;A, B&gt;(K&lt;App, A&gt; ma, Func&lt;A, K&lt;App, B&gt;&gt; f) =&gt;
        new App&lt;B&gt;(new ReaderT&lt;AppConfig, IO, B&gt;(config =&gt; ma.As().runService.Bind(a =&gt; f(a).Run(config)).Run(config)));

    public static K&lt;App, A&gt; LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
        new App&lt;A&gt;(ReaderT.liftIO&lt;AppConfig, IO, A&gt;(ma));

    public static K&lt;App, IO&lt;A&gt;&gt; ToIO&lt;A&gt;(K&lt;App, A&gt; ma) =&gt;
        new App&lt;IO&lt;A&gt;&gt;(ma.As().runService.ToIO().As());

    public static K&lt;App, A&gt; Asks&lt;A&gt;(Func&lt;AppConfig, A&gt; f) =&gt;
        new App&lt;A&gt;(ReaderT.asks&lt;IO, A, AppConfig&gt;(f));

    public static K&lt;App, A&gt; Local&lt;A&gt;(Func&lt;AppConfig, AppConfig&gt; f, K&lt;App, A&gt; ma) =&gt;
        new App&lt;A&gt;(ma.As().runService.Local(f));
}</code></pre><p>When you look closely you&apos;ll realise that every single implementation just defers to the underlying <code>ReaderT</code> transformer.  It&apos;s a true wrapper &#x2013; no bespoke code has been injected.</p><p>Although writing these wrappers around monad-transformer stacks isn&apos;t difficult, it&apos;s boilerplate that we could do without.  Luckily we can leverage our new higher-kinded trait skills to automate the wrapping and unwrapping of the inner-transformer.  </p><p>Introducing <code>Deriving</code>:</p><p>So, instead of inheriting the traits and implementing them, we will inherit <code>Deriving.</code> variants of those trait types:</p><pre><code class="language-csharp">public class App : 
    Deriving.MonadIO&lt;App, ReaderT&lt;AppConfig, IO&gt;&gt;, 
    Deriving.Readable&lt;App, AppConfig, ReaderT&lt;AppConfig, IO&gt;&gt;
{
    public static K&lt;ReaderT&lt;AppConfig, IO&gt;, A&gt; Transform&lt;A&gt;(K&lt;App, A&gt; fa) =&gt;
        fa.As().runService;

    public static K&lt;App, A&gt; CoTransform&lt;A&gt;(K&lt;ReaderT&lt;AppConfig, IO&gt;, A&gt; fa) =&gt;
        new App&lt;A&gt;(fa.As());   
}</code></pre><p>The only things we need to implement are <code>Transform</code> (which unwraps the inner-transformer), and <code>CoTransform</code> (that re-wraps it).  They&apos;re both incredibly efficient and provide default implementations which are passed through to the underlying transformer.  You get to use super reliable compositional components to build pure functional power-monads!</p><p>You don&apos;t even need to know how to implement any of these things, you can just wrap existing monad-transformers that are provided in language-ext, stack them how you like, and then use <code>Deriving.*</code> to build the trait-implementations automatically!</p><p>I&apos;ll document the <code>Deriving</code> functionality in a later article.  Just for know understand that even though it seems like magic, it&apos;s all beautifully type-safe and efficient!</p><h2 id="manually-implemented-transformers-removed">Manually implemented transformers removed</h2><p>Previous versions of language-ext had a number of monadic types that I have since removed:</p><ul><li><code>TryAsync&lt;A&gt;</code> &#x2013; can now be represented as <code>TryT&lt;IO, A&gt;</code></li><li><code>TryOption&lt;A&gt;</code> &#x2013; can now be represented as <code>OptionT&lt;Try, A&gt;</code></li><li><code>TryOptionAsync&lt;A&gt;</code> &#x2013; can now be represented as <code>OptionT&lt;TryT&lt;IO&gt;, A&gt;</code></li><li><code>OptionAsync&lt;A&gt;</code> &#x2013; can now be represented as <code>OptionT&lt;IO, A&gt;</code></li><li><code>EitherAsync&lt;L, R&gt;</code> &#x2013; can now be represented as <code>EitherT&lt;L, IO, A&gt;</code></li></ul><p>I have also had requests for <code>ValidationAsync&lt;F, S&gt;</code> over the years.  It can now be represented as <code>ValidationT&lt;F, IO, S&gt;</code>.  This all puts the control back in the hands of the users of this library and stops me being a blocker to new functionality.  It also significantly reduces the code footprint, which is a good thing for my sanity!</p><h2 id="ordering">Ordering</h2><p>The exact ordering of monads in the stack is another area where people often get confused.  Remember when you <code>Run</code> your stack you&apos;re unwrapping each layer one-by-one and depending on the order you may find you&apos;ve lost the resulting state you&apos;re after.  Also, certain transformers stack inside-out and some stack outside-in.  This can be quite confusing!  Just remember than you can always look at the wrapped nested type to get an intuition for how each transformer works.</p><p>For example, the <code>ReaderT</code> transformer works by making the lifted monad into the inner-monad (opposite to <code>MaybeT</code>):</p><pre><code class="language-csharp">ReaderT&lt;Env, M, A&gt;(Func&lt;Env, K&lt;M, A&gt;&gt; runReader)</code></pre><p>To a certain extent it takes a bit of trial and error to see what you get when you run the stack, but there&apos;s <a href="https://stackoverflow.com/questions/16457111/how-to-design-a-monadic-stack?ref=paullouth.com">some advice online</a>.  Language-ext&apos;s monad transformers work exactly the same way as Haskell&apos;s, so any online advice for stacking Haskell&apos;s transformers will work here too.</p><h2 id="performance">Performance</h2><p>For those of you who are performance-minded you may realise that nesting <code>n</code> monads into a super-monad comes with some overhead.  There&apos;s plenty of nested lambdas and they&apos;re not free.  Both from a memory allocations point-of-view, but also just the CPU cost of doing so.</p><p>Even though I spent my former life writing high-performance graphics engines for various Playstations, Xboxes, and the like, I firmly believe that large-scale professional application development should focus on correctness first and then performance afterwards.  The old adage of don&apos;t prematurely optimise is a good one!</p><p>The benefit of monad-transformers is that you can build a stack quite quickly without writing any new monad code; once you have your stack you can then wrap it up into a new type that hides the stack. You can rely on its <em>correctness</em> because you&apos;re just doing composition.  Then go and build your app.</p><p>At a later date if performance becomes a problem you can just replace the transformer-stack with a bespoke implementation of the transformer as a single monad (with all the features of the composed transformer).</p><p>This allows time for the stack to be updated depending on changes to requirements as your application evolves, but once the implementation has settled down, you can then consider replacing it with something bespoke.  </p><p><em>No other code needs to change.</em></p><p>True encapsulation.</p><h2 id="domain-monads">Domain Monads</h2><p>One of the most valuable uses for monad-transformers (especially more complex ones) is in modelling layers/domains in your architecture.  There are many approaches to this which will depend entirely on your code-base.  </p><p>I don&apos;t want to get too deep into architecture right now, but I&apos;ll provide a couple of examples from my latest startup project (this is early days for the project, so these may change, but it&apos;s good enough to demo for now):</p><p>I have a type called <code>Db&lt;A&gt;</code> it is the layer that talks directly to FoundationDB:</p><pre><code class="language-csharp">public record Db&lt;A&gt;(StateT&lt;DbEnv, IO, A&gt; runDB) : K&lt;Db, A&gt;
{
    public IO&lt;(A Value, DbEnv Env)&gt; Run(DbEnv env) =&gt;
        runDB.Run(env).As();

    public static Db&lt;A&gt; LiftIO(IO&lt;A&gt; ma) =&gt;
        new (StateT&lt;DbEnv, IO, A&gt;.LiftIO(ma));

    public static Db&lt;A&gt; operator |(Db&lt;A&gt; ma, Db&lt;A&gt; mb) =&gt;
        ma.Choose(mb).As();

    public Db&lt;B&gt; Map&lt;B&gt;(Func&lt;A, B&gt; f) =&gt;
        this.Kind().Map(f).As();

    public K&lt;Db, B&gt; MapIO&lt;B&gt;(Func&lt;IO&lt;A&gt;, IO&lt;B&gt;&gt; f) =&gt;
        this.Kind().MapIO(f).As();

    public Db&lt;B&gt; Bind&lt;B&gt;(Func&lt;A, Db&lt;B&gt;&gt; f) =&gt;
        this.Kind().Bind(f).As();
    
    public Db&lt;C&gt; SelectMany&lt;B, C&gt;(Func&lt;A, Db&lt;B&gt;&gt; bind, Func&lt;A, B, C&gt; project) =&gt;
        this.Kind().SelectMany(bind, project).As();
    
    public Db&lt;C&gt; SelectMany&lt;B, C&gt;(Func&lt;A, IO&lt;B&gt;&gt; bind, Func&lt;A, B, C&gt; project) =&gt;
        this.Kind().SelectMany(bind, project).As();

    public static implicit operator Db&lt;A&gt;(Pure&lt;A&gt; ma) =&gt;
        Db.pure(ma.Value).As();
    
    public static implicit operator Db&lt;A&gt;(Fail&lt;Error&gt; ma) =&gt;
        Db.fail&lt;A&gt;(ma.Value);
    
    public static implicit operator Db&lt;A&gt;(Fail&lt;string&gt; ma) =&gt;
        Db.fail&lt;A&gt;(ma.Value);
    
    public static implicit operator Db&lt;A&gt;(Error ma) =&gt;
        Db.fail&lt;A&gt;(ma);
}</code></pre><p>Things to note are:</p><ul><li>It wraps <code>StateT&lt;DBEnv, IO, A&gt;</code> &#x2013; so it packages up the state generic argument and its IO nature.</li><li>You can see lots of methods implemented like this: <ul><li><code>this.Kind().XXX.As();</code></li><li><code>Kind</code> converts to the underlying generic trait <code>K&lt;Db, A&gt;</code> </li><li>We then call the trait implementation for <code>XXX</code>.</li><li>Then we convert back to <code>Db&lt;A&gt;</code> using <code>As()</code></li><li>This allows us to defer the actual implementation of these functions to the trait-implementation.  This concrete surface to the type could easily be generated with source-generators in the future (it&apos;s on my list!).</li></ul></li></ul><p>Because we&apos;ve deferred the responsibility for implementing the methods above to the trait implementation.  Let&apos;s take a look at it...</p><pre><code class="language-csharp">public partial class Db :
    Deriving.Monad&lt;Db, StateT&lt;DbEnv, IO&gt;&gt;,
    Deriving.Stateful&lt;Db, StateT&lt;DbEnv, IO&gt;, DbEnv&gt;,
    Deriving.Choice&lt;Db, StateT&lt;DbEnv, IO&gt;&gt;,
    Fallible&lt;Db&gt;,
    MonadIO&lt;Db&gt;
{
    static K&lt;StateT&lt;DbEnv, IO&gt;, A&gt; Natural&lt;Db, StateT&lt;DbEnv, IO&gt;&gt;.Transform&lt;A&gt;(K&lt;Db, A&gt; fa) =&gt; 
        fa.As().runDB;

    static K&lt;Db, A&gt; CoNatural&lt;Db, StateT&lt;DbEnv, IO&gt;&gt;.CoTransform&lt;A&gt;(K&lt;StateT&lt;DbEnv, IO&gt;, A&gt; fa) =&gt; 
        new Db&lt;A&gt;(fa.As());    

    static K&lt;Db, A&gt; Maybe.MonadIO&lt;Db&gt;.LiftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
        new Db&lt;A&gt; (StateT&lt;DbEnv, IO, A&gt;.LiftIO(ma));

    static K&lt;Db, IO&lt;A&gt;&gt; Maybe.MonadIO&lt;Db&gt;.ToIO&lt;A&gt;(K&lt;Db, A&gt; ma) =&gt;
        dbEnv.Map(e =&gt; ma.As().Run(e).Map(r =&gt; r.Value));  // NOTE: This ignores the returned state

    static K&lt;Db, B&gt; Maybe.MonadIO&lt;Db&gt;.MapIO&lt;A, B&gt;(K&lt;Db, A&gt; ma, Func&lt;IO&lt;A&gt;, IO&lt;B&gt;&gt; f) =&gt; 
        from e in dbEnv
        from r in f(ma.As().runDB.Run(e).Map(vs =&gt;vs.Value).As())   // NOTE: This ignores the returned state
        select r;

    static K&lt;Db, A&gt; Fallible&lt;Error, Db&gt;.Fail&lt;A&gt;(Error error) =&gt; 
        new Db&lt;A&gt;(StateT.lift&lt;DbEnv, IO, A&gt;(IO.fail&lt;A&gt;(error)));

    static K&lt;Db, A&gt; Fallible&lt;Error, Db&gt;.Catch&lt;A&gt;(K&lt;Db, A&gt; ma, Func&lt;Error, bool&gt; Predicate, Func&lt;Error, K&lt;Db, A&gt;&gt; Fail) =&gt; 
        from e in dbEnv
        from r in liftIO(ma.As().runDB.Run(e).Catch(Predicate, err =&gt; Fail(err).As().Run(e)).As())
        from _ in Stateful.put&lt;Db, DbEnv&gt;(r.Item2)
        select r.Value;
}

</code></pre><p>Things to note:</p><ul><li>Three uses of <code>Deriving.*</code> so we don&apos;t have to manually implement <code>Monad</code>, <code>Stateful</code>, or <code>Choice</code>.</li><li>We<em> do</em> implement <code>MonadIO</code> and <code>Fallible</code>, because <code>StateT</code> doesn&apos;t support those traits.  You can see the compromise in the <code>LiftIO</code> and <code>ToIO</code> methods &#x2013; <code>StateT</code> can&apos;t support those without losing its state.  I know that&apos;s OK for this use-case but can&apos;t be generalised.</li></ul><p>Looking at just the traits it&apos;s clear to see that this type is: a monad, manages state, handles failure (<code>Fallible</code>), alternatives (<code>Choice</code> or the <code>|</code> operator), <em>and </em>IO.</p><p>Once you have your domain-type defined and its traits implemented.  You can create the API to your domain...</p><blockquote>Comments and some implementation details removed for clarity</blockquote><pre><code class="language-csharp">public partial class Db
{
    public static Db&lt;A&gt; pure&lt;A&gt;(A value) =&gt;
        Applicative.pure&lt;Db, A&gt;(value).As();

    public static Db&lt;A&gt; fail&lt;A&gt;(string error) =&gt;
        Fallible.error&lt;Db, A&gt;((Error)error).As();

    public static Db&lt;A&gt; fail&lt;A&gt;(Error error) =&gt;
        Fallible.error&lt;Db, A&gt;(error).As();

    public static readonly Db&lt;DbEnv&gt; dbEnv = 
        Stateful.get&lt;Db, DbEnv&gt;().As(); 
    
    internal static Db&lt;A&gt; gets&lt;A&gt;(Func&lt;DbEnv, A&gt; f) =&gt; 
        Stateful.gets&lt;Db, DbEnv, A&gt;(f).As();
    
    public static Db&lt;Unit&gt; put(DbEnv env) =&gt; 
        Stateful.put&lt;Db, DbEnv&gt;(env).As();

    public static Db&lt;A&gt; liftIO&lt;A&gt;(IO&lt;A&gt; ma) =&gt;
        MonadIO.liftIO&lt;Db, A&gt;(ma).As();

    internal static Db&lt;A&gt; liftIO&lt;A&gt;(Func&lt;DbEnv, EnvIO, A&gt; f) =&gt;
        dbEnv.Bind(env =&gt; IO.lift(envIO =&gt; f(env, envIO))).As();

    internal static Db&lt;A&gt; liftIO&lt;A&gt;(Func&lt;EnvIO, A&gt; f) =&gt;
        MonadIO.liftIO&lt;Db, A&gt;(IO.lift(f)).As();

    internal static Db&lt;A&gt; liftIO&lt;A&gt;(Func&lt;DbEnv, EnvIO, Task&lt;A&gt;&gt; f) =&gt;
        dbEnv.Bind(env =&gt; IO.liftAsync(async envIO =&gt; await f(env, envIO).ConfigureAwait(false))).As();

    internal static Db&lt;A&gt; liftIO&lt;A&gt;(Func&lt;EnvIO, Task&lt;A&gt;&gt; f) =&gt;
        MonadIO.liftIO&lt;Db, A&gt;(IO.liftAsync(async e =&gt; await f(e).ConfigureAwait(false))).As();

    static Db&lt;Unit&gt; fdbVersion =
        liftIO(...).Memo();
    
    public static Db&lt;Unit&gt; shutdown =
        liftIO(...);
    
    public static readonly Db&lt;Unit&gt; connect =
        (from ver in fdbVersion
         from env in dbEnv
         from con in liftIO(...)
         from res in put(env with { Database = Some(con) })
         select unit)
        .Memo();

    static readonly Db&lt;IFdbDatabase&gt; db =
        gets&lt;IFdbDatabase&gt;(...);

    static readonly Db&lt;IFdbTransaction&gt; transaction =
        gets&lt;IFdbTransaction&gt;(...);
    
    static readonly Db&lt;IFdbReadOnlyTransaction&gt; readOnlyTransaction =
        gets&lt;IFdbReadOnlyTransaction&gt;(...);

    public static Db&lt;A&gt; subspace&lt;A&gt;(string leaf, K&lt;Db, A&gt; ma) =&gt;
        subspace(FdbPath.Relative(leaf), ma);

    public static Db&lt;A&gt; subspace&lt;A&gt;(FdbPath path, K&lt;Db, A&gt; ma) =&gt;
       from t in readOnlyTransaction
       from r in liftIO(...)
       select r;

    public static Db&lt;A&gt; readOnly&lt;A&gt;(FdbPath subspacePath, K&lt;Db, A&gt; ma) =&gt;
        readOnly(subspace(subspacePath, ma));

    public static Db&lt;A&gt; readOnly&lt;A&gt;(K&lt;Db, A&gt; ma) =&gt;
        connect.Bind(_ =&gt; liftIO(...));

    public static Db&lt;A&gt; readWrite&lt;A&gt;(FdbPath subspacePath, K&lt;Db, A&gt; ma) =&gt;
        readWrite(subspace(subspacePath, ma));

    public static Db&lt;A&gt; readWrite&lt;A&gt;(K&lt;Db, A&gt; ma) =&gt;
        connect.Bind(_ =&gt; liftIO(...));

    public static Db&lt;Slice&gt; get(string name) =&gt;
        liftIO(...);
    
    public static Db&lt;Unit&gt; set&lt;A&gt;(string name, A value) =&gt;  
        liftIO(...);

    public static Db&lt;uint&gt; increment32(string name) =&gt;  
        liftIO(...);
    
    public static Db&lt;ulong&gt; increment64(string name) =&gt;  
        liftIO(...);
}</code></pre><p>The <code>Db&lt;A&gt;</code> monad then becomes the &apos;layer&apos; that wraps my database.  It manages connections, security, etc.  I just need to write code like this:</p><pre><code class="language-csharp">public static Db&lt;VerificationId&gt; generateEmailVerifyId(EmailAddress email) =&gt;
    from vid in Db.liftIO(randomCode)
    from res in Db.subspace(Subspaces.ValidationEmail,
                            Db.set(vid, email.To()))
    select VerificationId.From(vid);
</code></pre><p>In the same project I have a <code>Service&lt;A&gt;</code> monad.  Its job is to talk to external services.  The idea being is its a protected gateway to the outside world, but also it knows various configuration settings, which enables it to know how to talk to the outside world.</p><p>It looks like this:</p><pre><code class="language-csharp">public record Service&lt;A&gt;(ReaderT&lt;ServiceEnv, IO, A&gt; runService) : K&lt;Service, A&gt;
{
   ...
}
</code></pre><p>So, this time we&apos;re using the <code>ReaderT</code> monad with a fixed environment (which carries the configuration).  And it also does IO like the <code>Db&lt;A&gt;</code> monad.</p><p>It enables code like this:</p><pre><code class="language-csharp">public static Service&lt;Unit&gt; sendVerifyEmail(EmailAddress email, VerificationId verifyId) =&gt;
    from ky in Service.sendGridApiKey
    from rt in Service.webRoot
    from r1 in Service.liftIO(...)
    from r2 in r1.StatusCode == HttpStatusCode.Accepted
                   ? Service.pure(unit)
                   : Service.fail&lt;Unit&gt;(ServiceError.EmailDeliveryFailed(email))
    select r2;</code></pre><p>So, that&apos;s two domains we&apos;ve created (database and external services).  Could we use them side-by-side?</p><p>Well, just to completely blow your mind.  I have an <code>Api&lt;A&gt;</code> monad.  It is not a transformer monad, it&apos;s a <code>Free</code> monad.  </p><blockquote>I&apos;ll cover <code>Free</code> monads properly in a later article, but I&apos;ll give you a quick insight into how we can join these two domain-monads together.  It&apos;s nothing to do with transformers really, but I hope it gives you some food for thought!</blockquote><p>First, I have a DSL which is a simple-union:</p><pre><code class="language-csharp">public abstract record ApiDsl&lt;A&gt; : K&lt;ApiDsl, A&gt;;
public record ApiFail&lt;A&gt;(Error Error) : ApiDsl&lt;A&gt;;
public record ApiDb&lt;A&gt;(Db&lt;A&gt; Action) : ApiDsl&lt;A&gt;;
public record ApiService&lt;A&gt;(Service&lt;A&gt; Action) : ApiDsl&lt;A&gt;;</code></pre><blockquote>Notice how two of the cases wrap up <code>Db&lt;A&gt;</code> and <code>Service&lt;A&gt;</code>.</blockquote><p>Then I make it into a <code>Functor</code> and add some convenience functions for constructing the cases of the DSL.</p><pre><code class="language-csharp">public class ApiDsl : Functor&lt;ApiDsl&gt;
{
    static K&lt;ApiDsl, B&gt; Functor&lt;ApiDsl&gt;.Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;ApiDsl, A&gt; ma) =&gt;
        ma switch
        {
            ApiFail&lt;A&gt;(var error) =&gt; new ApiFail&lt;B&gt;(error),
            ApiDb&lt;A&gt;(var action)  =&gt; new ApiDb&lt;B&gt;(action.Map(f)),
            ApiService&lt;A&gt;(var action)  =&gt; new ApiService&lt;B&gt;(action.Map(f))
        };

    public static Free&lt;ApiDsl, A&gt; fail&lt;A&gt;(Error value) =&gt;
        Free.lift(new ApiFail&lt;A&gt;(value));

    public static Free&lt;ApiDsl, A&gt; db&lt;A&gt;(Db&lt;A&gt; value) =&gt;
        Free.lift(new ApiDb&lt;A&gt;(value));

    public static Free&lt;ApiDsl, A&gt; service&lt;A&gt;(Service&lt;A&gt; value) =&gt;
        Free.lift(new ApiService&lt;A&gt;(value));
}</code></pre><p>Now I need to create an <code>Api&lt;A&gt;</code> type that wraps the <code>Free</code> monad (similar to how we do with the transformers):</p><pre><code class="language-csharp">public record Api&lt;A&gt;(Free&lt;ApiDsl, A&gt; runApi) : K&lt;Api, A&gt;
{
    public Api&lt;B&gt; Map&lt;B&gt;(Func&lt;A, B&gt; f) =&gt;
        this.Kind().Map(f).As();

    public Api&lt;B&gt; Select&lt;B&gt;(Func&lt;A, B&gt; f) =&gt;
        this.Kind().Map(f).As();

    public Api&lt;B&gt; Bind&lt;B&gt;(Func&lt;A, Api&lt;B&gt;&gt; f) =&gt;
        this.Kind().Bind(f).As();
    
    public Api&lt;C&gt; SelectMany&lt;B, C&gt;(Func&lt;A, Api&lt;B&gt;&gt; bind, Func&lt;A, B, C&gt; project) =&gt;
        this.Kind().SelectMany(bind, project).As();
    
    public Api&lt;C&gt; SelectMany&lt;B, C&gt;(Func&lt;A, IO&lt;B&gt;&gt; bind, Func&lt;A, B, C&gt; project) =&gt;
        this.Kind().SelectMany(bind, project).As();

    public static implicit operator Api&lt;A&gt;(Pure&lt;A&gt; ma) =&gt;
        Api.pure(ma.Value).As();
    
    public static implicit operator Api&lt;A&gt;(Fail&lt;Error&gt; ma) =&gt;
        Api.fail&lt;A&gt;(ma.Value);
    
    public static implicit operator Api&lt;A&gt;(Fail&lt;string&gt; ma) =&gt;
        Api.fail&lt;A&gt;(ma.Value);
    
    public static implicit operator Api&lt;A&gt;(Error ma) =&gt;
        Api.fail&lt;A&gt;(ma);
}
</code></pre><p>Then we create the trait implementation:</p><pre><code class="language-csharp">public partial class Api : 
  Deriving.Choice&lt;Api, Free&lt;ApiDsl&gt;&gt;,
  Deriving.MonadIO&lt;Api, Free&lt;ApiDsl&gt;&gt;
{
    static K&lt;Free&lt;ApiDsl&gt;, A&gt; Natural&lt;Api, Free&lt;ApiDsl&gt;&gt;.Transform&lt;A&gt;(K&lt;Api, A&gt; fa) =&gt;
        fa.As().runApi;

    static K&lt;Api, A&gt; CoNatural&lt;Api, Free&lt;ApiDsl&gt;&gt;.CoTransform&lt;A&gt;(K&lt;Free&lt;ApiDsl&gt;, A&gt; fa) =&gt; 
        new Api&lt;A&gt;(fa.As());
}

</code></pre><p>Just like with the transformers, we&apos;re just deferring to the underlying type that we&apos;re wrapping.  In this case the <code>Free</code> monad.</p><p>Now we need a friendly API to our <code>Api&lt;A&gt;</code> monad:</p><pre><code class="language-csharp">public partial class Api
{
    public static Api&lt;A&gt; pure&lt;A&gt;(A value) =&gt;
        new (Free.pure&lt;ApiDsl, A&gt;(value));
    
    public static Api&lt;A&gt; fail&lt;A&gt;(Error value) =&gt;
        new (ApiDsl.fail&lt;A&gt;(value));
    
    public static Api&lt;A&gt; fail&lt;A&gt;(string value) =&gt;
        new (ApiDsl.fail&lt;A&gt;((Error)value));
    
    public static Api&lt;A&gt; lift&lt;A&gt;(Db&lt;A&gt; ma) =&gt;
        new (ApiDsl.db(ma));
    
    public static Api&lt;A&gt; readOnly&lt;A&gt;(Db&lt;A&gt; ma) =&gt;
        new (ApiDsl.db(Db.readOnly(ma)));
    
    public static Api&lt;A&gt; readOnly&lt;A&gt;(FdbPath subSpacePath, Db&lt;A&gt; ma) =&gt;
        new (ApiDsl.db(Db.readOnly(subSpacePath, ma)));
    
    public static Api&lt;A&gt; readWrite&lt;A&gt;(Db&lt;A&gt; ma) =&gt;
        new (ApiDsl.db(Db.readWrite(ma)));
    
    public static Api&lt;A&gt; readWrite&lt;A&gt;(FdbPath subSpacePath, Db&lt;A&gt; ma) =&gt;
        new (ApiDsl.db(Db.readWrite(subSpacePath, ma)));
    
    public static Api&lt;A&gt; lift&lt;A&gt;(Service&lt;A&gt; ma) =&gt;
        new (ApiDsl.service(ma));
}</code></pre><p>These functions make it easy to construct an API monad in whatever DSL state we like.  Notice how we lift both the <code>Db&lt;A&gt;</code> and the <code>Service&lt;A&gt;</code> into the <code>Api&lt;A&gt;</code> monad.</p><p>Now we can write code:</p><pre><code class="language-csharp">public static Api&lt;Unit&gt; register(EmailAddress email, PhoneNumber phone, Password password) =&gt;
    from id in Api.readWrite(from _ in Credential.createUser(email, phone, password)
                             from t in Verification.generateEmailVerifyId(email)
                             select t)
    from _  in Api.lift(Email.sendVerifyEmail(email, id))
    select unit;
</code></pre><p>We have two blocks:</p><ul><li>One which is the <code>Db&lt;A&gt;</code> that interacts with the database</li><li>One which is the <code>Service&lt;A&gt;</code> that interacts with third-party services</li></ul><p>These are both <em>lifted</em> into the <code>Api&lt;A&gt;</code> monad (via <code>readWrite</code> and <code>lift</code>).  Notice how we automatically segregate our transactional DB code from our service-action code.  This encourages us to write performant code without even trying!</p><p>What about running this?  If you understand anything about <code>Free</code> monads, then you&apos;ll know they need an interpreter.  So, let&apos;s write that:</p><pre><code class="language-csharp">    public IO&lt;A&gt; Run(DbEnv dbEnv, ServiceEnv serviceEnv) =&gt;
        Interpret(dbEnv, serviceEnv, runApi);

    static IO&lt;A&gt; Interpret(DbEnv dbEnv, ServiceEnv serviceEnv, Free&lt;ApiDsl, A&gt; fma)
    {
        return go(fma);
        
        IO&lt;A&gt; go(Free&lt;ApiDsl, A&gt; ma) =&gt;
            ma switch
            {
                Pure&lt;ApiDsl, A&gt;(var value) =&gt; 
                    IO.pure(value),
                
                Bind&lt;ApiDsl, A&gt;(var bind) =&gt;
                    bind switch
                    {
                        ApiFail&lt;Free&lt;ApiDsl, A&gt;&gt; (var e) =&gt;
                            IO.Fail&lt;A&gt;(e),

                        ApiDb&lt;Free&lt;ApiDsl, A&gt;&gt; (var db) =&gt;
                            db.Map(go)
                              .Run(dbEnv)
                              .Map(x =&gt; x.Value)
                              .Flatten(),
                        
                        ApiService&lt;Free&lt;ApiDsl, A&gt;&gt; (var service) =&gt;
                            service.Map(go)
                                   .Run(serviceEnv)
                                   .Flatten(),
                        
                        _ =&gt; throw new NotSupportedException()
                    }
            };
    }</code></pre><p>It&apos;s not particularly pretty, but it is just a recursive pattern-match operation.  </p><p>Things to note are:</p><ul><li>The <code>Pure</code> and <code>Bind</code> cases are from the <code>Free</code> monad itself.  <ul><li>Think: <code>Pure</code> means &quot;we&apos;re done&quot; and <code>Bind</code> means &quot;continue&quot;</li></ul></li><li>The cases of the <code>ApiDsl</code> actually run the <code>Db&lt;A&gt;</code> and <code>Service&lt;A&gt;</code> monads.  <ul><li>They also feed in the external state or configuration (which is passed to the <code>Interpret</code> method),</li><li>Because they both have <code>IO</code> monads in their transformer stack, we can unwrap the stack to that level and then return it from the interpreter as its base monad.  Meaning the <code>Api</code> monad is an <code>IO</code> monad also!</li></ul></li></ul><p>Hopefully you can imagine a web-request or an event of some sort calling the <code>register</code> function from earlier:</p><pre><code class="language-csharp">var action = Registration.register(email, phone, pass);</code></pre><p>And then running it with the database-environment, configuration, and an IO environment (which enables cancellation and the like):</p><pre><code class="language-csharp">var result = action.Run(dbEnv, serviceEnv)
                   .Run(envIO);
</code></pre><p>And so, what we&apos;ve done here is compose various built-in monads and monad-transformers from language-ext (<code>ReaderT</code>, <code>StateT</code>, <code>IO</code>), wrapped them up into domain-specific monads: <code>Db&lt;A&gt;</code> and <code>Service&lt;A&gt;</code> and then lifted those into another domain-monad that is implemented using the <code>Free</code> monad: <code>Api&lt;A&gt;</code> to give us a surface that manages:</p><ul><li>IO</li><li>State</li><li>Configuration</li><li>Security</li><li>Transaction management</li><li>Resource tracking</li><li>And, segregation of operations that shouldn&apos;t mix!</li></ul><p>The resulting domain-monads don&apos;t expose their underlying form until they are <em>run</em>. We try to hide the monad-transformer stacks and the states of the free-monad so that if we need to change it at a later date it is easy.  It also means if I ever want more performance I can just go in and manually write those monads.</p><blockquote>It should be noted that these techniques aren&apos;t slow.  They&apos;re just slow<em>er</em> than hand-crafted solutions.  The chances are they&apos;re plenty fast enough for 99% of use-cases, so don&apos;t get too caught up on the idea that you have to go in and optimise early.  As always: profile your code! </blockquote><h2 id="conclusion">Conclusion</h2><p>It may seem like this is one of the most convoluted ways to compose functionality going.  And yeah, there&apos;s a bit of typing overhead here.  But really, we build these domain monads a handful of times for a project, this isn&apos;t a daily job of creating new monad-transformer stacks. Personally, I think it&apos;s well worth building domain-monads and I think it&apos;s well worth leveraging the existing transformers to create your domain-monads.</p><p>Build your stack based on the features you need.  Then box it to make it easy to use and consume.  The API surface you build for your transformer stack <em>is the the feature</em>.  The monad and transformer bit just makes the basics work, so don&apos;t forget to make a good domain API surface to get the most out of this approach!</p><p>In the <a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-10-readert-monad-transformer/">next article</a> we&apos;ll cover some more monad-transformers and more techniques to make working with transformers even more powerful.</p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 8- monads continued]]]></title><description><![CDATA[We delve into specific 'flavours' of monad by showing how to implement many of the key monadic types in language-ext.]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/</link><guid isPermaLink="false">6639c7812ac0342e8bc945de</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[hkt]]></category><category><![CDATA[monad]]></category><category><![CDATA[language-ext]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Tue, 07 May 2024 17:59:04 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/05/monads-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/05/monads-2.png" alt="Higher Kinds in C# with language-ext [Part 8- monads continued]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow this &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li><li><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads</a></li></ul><p>In the last episode we finally defined the <code>Monad&lt;M&gt;</code> trait and learned the reason for monads:</p><ul><li>Enables pure functional programmers to sequence operations<ul><li>The operations have a particular &apos;flavour&apos; which defines what happens between the operations (<code>Bind</code>)</li></ul></li><li>Encapsulates messy impure side-effects and effects</li><li>Results in a singular <em>pure</em> expression</li></ul><p>But what are effects and side-effects?  This is something that I think even seasoned pure-FP programmers aren&apos;t always clear on.  Side-effects are fairly obvious: anything that changes the state of the world (writes to a file, adds a row to a database, changes a global variable, etc.) &#x2013; but what about &apos;effects&apos;?</p><p>When we have a pure and total function, you could imagine that the internals of it could be swapped for a switch expression.  For example, let&apos;s make an <code>IsEven</code> function:</p><pre><code class="language-csharp">bool IsEven(int x) =&gt;
  (x &amp; 1) == 0;</code></pre><p>Instead of using the bitwise AND operation, let&apos;s swap it for a switch:</p><pre><code class="language-csharp">bool IsEven(int x) =&gt;
   x switch
   {
       0 =&gt; true,
       1 =&gt; false,
       2 =&gt; true,
       3 =&gt; false,
       ...
   };</code></pre><p>Clearly, it would be a huge function!  But that&apos;s the way to think about pure functions.  They are a mapping from the input arguments to the output. They are also a <em>&apos;zero time&apos;</em> operation. I don&apos;t mean they take zero processor cycles to complete, I mean by having zero impact on the outside world (no event happened) we can consider the transformation to have been <em>instant</em>.  </p><p>Whereas non-pure functions change the world and so we have cause and effect (time) &#x2013; this turns out to be a remarkably profound observation if you think about it &#x2013; especially when considering software complexity.</p><p>In some circumstances a switch expression wouldn&apos;t be able to cover all of the possible input states.  So, we augment the output by using data-types like <code>Option</code>, <code>Either</code>, <code>Fin</code>, <code>Validation</code>, etc.  But the act of adding an extra value (<code>None</code>, <code>Left</code>, <code>Fail</code>, etc.) to the co-domain doesn&apos;t instantly make an effect &#x2013; it&apos;s the <em>behaviour change</em> that comes as a result of the additional elements in the co-domain that is the effect.  For example, when we sequence multiple <code>Option</code> returning computations, the <em>effect </em>is to exit early when we return <code>None</code>.</p><p>So, monads capture side-effects and effects (&apos;side-effects&apos; being a subset of &apos;effects&apos;).  The nature of the effect is the bespoke behaviour of the monad. </p><blockquote>Effects are still &apos;felt&apos; for applicatives and functors too.  The <code>Map</code> function won&apos;t be invoked if the <code>Option</code> is in a <code>None</code> state for example.  So, all of these higher-kinded abstractions get involved in the &apos;effectfulness&apos;.</blockquote><h3 id="flatten">Flatten</h3><p>Another part of the <code>Monad&lt;M&gt;</code> trait is <code>Flatten</code> which is also known as &apos;monad join&apos; in other ecosystems.  There&apos;s a default implementation, so you never need to write it yourself, but it&apos;s worth understanding that there are <em>two ways to implement a monad (Gah! Not another Yet Another Monad Tutorial, please!)</em></p><p>Let&apos;s look at the method-signature for <code>Flatten</code>:</p><pre><code class="language-csharp">K&lt;M, A&gt; Flatten&lt;A&gt;(K&lt;M, K&lt;M, A&gt;&gt; mma)</code></pre><p><code>Flatten</code> takes a nested monad (like <code>Option&lt;Option&lt;A&gt;&gt;</code> or <code>IO&lt;IO&lt;A&gt;&gt;</code>) and <em>&apos;flattens&apos;</em> it so it&apos;s not nested any more.  To do this it must <em>compute </em>the outer monad to get to the inner monad. The behaviour is kinda similar to <code>Bind</code> without the mapping part.</p><p>So, if you override <code>Flatten</code> in your monad implementation, then the simplest way to implement it is in terms of <code>Bind</code> and the <code>identity</code> function:</p><pre><code class="language-csharp">public static K&lt;Maybe, A&gt; Flatten&lt;A&gt;(K&lt;Maybe, K&lt;Maybe, A&gt;&gt; mma) =&gt;
    mma.Bind(identity);
</code></pre><blockquote><em>That&apos;s why we can easily provide a default implementation!</em>  </blockquote><p>However, we could implement it <em>without</em> referencing <code>Bind</code>.  Here&apos;s an example of implementing <code>Flatten</code> for <code>Maybe</code>:</p><pre><code class="language-csharp">public static K&lt;Maybe, A&gt; Flatten&lt;A&gt;(K&lt;Maybe, K&lt;Maybe, A&gt;&gt; mma) =&gt;
    mma switch
    {
        Just&lt;K&lt;Maybe, A&gt;&gt; (var ma) =&gt; ma,
        Nothing&lt;K&lt;Maybe, A&gt;&gt;       =&gt; new Nothing&lt;A&gt;()
    };
</code></pre><p>We pattern-match the outer-<code>Maybe</code>, if it&apos;s in a <code>Just</code> state, then the value inside will be what we need to return.  If it&apos;s in a <code>Nothing</code> state then we just create a new <code>Nothing&lt;A&gt;</code>.  </p><p>Why&apos;s that important?  Well we can now implement <code>Bind</code> in terms of <code>Flatten</code> and <code>Map</code>:</p><pre><code class="language-csharp">public static K&lt;Maybe, B&gt; Bind&lt;A, B&gt;(K&lt;Maybe, A&gt; ma, Func&lt;A, K&lt;Maybe, B&gt;&gt; f) =&gt;
    ma.Map(f).Flatten();
</code></pre><blockquote>This is why <code>Bind</code> is sometimes also called <code>FlatMap</code>.</blockquote><p>Again, so what?  Why do we care?  Really, you don&apos;t need to care, it&apos;s purely down to which implementation is <em>easiest</em> or <em>most efficient</em>.  So, you either implement <code>Bind</code> in terms of <code>Flatten</code> and <code>Map</code>, or you implement <code>Flatten</code> in terms of <code>Bind</code> (the default).  Or, you could have bespoke implementations for both!  Just remember when implementing your own monads that there are two distinct routes to implementing a monad &#x2013; one route may be better than the other.</p><h2 id="flavours">Flavours</h2><p>I&apos;m going to spend the rest of this article showing implementations of monads for the various types that are in language-ext (other than the compound monads, like <code>Eff&lt;A&gt;</code>).  </p><p>These will just be the raw monads/applicatives/functors, none of the support functions ( which are the &apos;API&apos; of a data-type with a monad trait).  The code below is enough for you to use these monads and leverage the built-in functionality of language-ext (functionality that targets traits like <code>Monad&lt;M&gt;</code>, for example), but you&apos;ll realise &#x2013; once you start building monads yourself &#x2013; it&apos;s the <em>supplementary</em> support functions that leverage the monad that are the key. </p><p>The reason I highlight this is, up until now, users of language-ext have taken monads <em>&apos;off the shelf&apos;</em> (like <code>Option</code>, <code>Eff</code>, etc.) &#x2013; but now you&apos;re able to build your own.  It&apos;s important to understand that you can build your own monads just like you would classes in OOP.  They&apos;re no more special than any other type you might build that has bespoke functionality.  The main difference is that they&apos;re cross-cutting computations, if &apos;inheritance&apos; is top-down, then monads are slice-thru!</p><p>To give you a quick insight into what I mean, I am currently dog-fooding <code>v5</code> language-ext with a new project I am building.  Below are some of (not all!) the bespoke monads in the project:</p><ul><li><code>Db&lt;A&gt;</code> &#x2013; which manages interaction with FoundationDB.  It manages state (sub-spaces, connections, etc.), security, and does IO.</li><li><code>Service&lt;A&gt;</code> &#x2013; which are for access to 3rd party services, like SendGrid.  It tracks resources, security, handles configuration, and does IO.</li><li><code>Api&lt;A&gt;</code> &#x2013; which is a <code>Free</code> monad (I&apos;ll discuss in a later article) that wraps up interaction with the various subsystems, tracks resource usage, and provides configuration.</li><li>etc.</li></ul><p>When people talk about &apos;layers&apos; in classic software architecture, you can create <em>layer-monads </em>or, more broadly: <em>domain-monads,</em> that enforce anything you want &#x2013; it could be security, resource management, logging, whatever!</p><p>With (the monads below) I won&apos;t provide too much running commentary. After the last article, which was very much about the philosophy, I want to instead present some actual implementations.  You should just examine the <code>Bind</code> function for each type to see what each monad does differently (or often how similar they are to each other!).</p><h3 id="maybea">Maybe&lt;A&gt;</h3><blockquote><strong>Effect:</strong> Early termination of computation when in a <code>None</code> state.</blockquote><pre><code class="language-csharp">// Maybe data-type (same functionality as Option)
public abstract record Maybe&lt;A&gt; : K&lt;Maybe, A&gt;;
public record Just&lt;A&gt;(A Value) : Maybe&lt;A&gt;;
public record Nothing&lt;A&gt; : Maybe&lt;A&gt;;

// Maybe trait implementation
public class Maybe : Monad&lt;Maybe&gt;
{
    public static K&lt;Maybe, B&gt; Bind&lt;A, B&gt;(K&lt;Maybe, A&gt; ma, Func&lt;A, K&lt;Maybe, B&gt;&gt; f) =&gt;
        ma switch
        {
            Just&lt;A&gt; (var x) =&gt; f(x),
            Nothing&lt;A&gt;      =&gt; new Nothing&lt;B&gt;()
        };

    public static K&lt;Maybe, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Maybe, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Maybe, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Just&lt;A&gt;(value);

    public static K&lt;Maybe, B&gt; Apply&lt;A, B&gt;(K&lt;Maybe, Func&lt;A, B&gt;&gt; mf, K&lt;Maybe, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}</code></pre><h3 id="eitherl-r">Either&lt;L, R&gt;</h3><blockquote><strong>Effect:</strong> Early termination of computation when in a <code>Left</code> state.  <code>Left</code> carries a &apos;failure&apos; value.</blockquote><pre><code class="language-csharp">// Either data-type
public abstract record Either&lt;L, R&gt; : K&lt;Either&lt;L&gt;, R&gt;;
public record Right&lt;L, R&gt;(R Value) : Either&lt;L, R&gt;;
public record Left&lt;L, R&gt;(L Value) : Either&lt;L, R&gt;;

// Either trait implementation
public class Either&lt;L&gt; : Monad&lt;Either&lt;L&gt;&gt;
{
    public static K&lt;Either&lt;L&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;Either&lt;L&gt;, A&gt; ma, Func&lt;A, K&lt;Either&lt;L&gt;, B&gt;&gt; f) =&gt;
        ma switch
        {
            Right&lt;L, A&gt;(var r) =&gt; f(r),
            Left&lt;L, A&gt; (var x) =&gt; new Left&lt;L, B&gt;(x) // carries the error through
        };

    public static K&lt;Either&lt;L&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Either&lt;L&gt;, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Either&lt;L&gt;, R&gt; Pure&lt;R&gt;(R value) =&gt;
        new Right&lt;L, R&gt;(value);

    public static K&lt;Either&lt;L&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;Either&lt;L&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;Either&lt;L&gt;, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}</code></pre><h3 id="fina">Fin&lt;A&gt;</h3><blockquote><strong>Effect: </strong>Exactly the same as <code>Either&lt;Error, A&gt;</code> </blockquote><p>This bakes in the <code>Error</code> type to capture the most common result of any C# function: either an error or a result.  Those who used <code>Result&lt;A&gt;</code> in <code>v4</code> should be using <code>Fin&lt;A&gt;</code> (&apos;fin&apos; being French for final/finished &#x2013; synonym for &apos;result&apos;).  This is easier to use than <code>Either&lt;Error, A&gt;</code> as it doesn&apos;t require the application of two generic arguments.</p><pre><code class="language-csharp">// Fin data-type (same functionality as Either&lt;Error, A&gt;)
public abstract record Fin&lt;A&gt; : K&lt;Fin, A&gt;;
public record Succ&lt;A&gt;(A Value) : Fin&lt;A&gt;;
public record Fail&lt;A&gt;(Error Value) : Fin&lt;A&gt;;

// Fin traits
public class Fin : Monad&lt;Fin&gt;
{
    public static K&lt;Fin, B&gt; Bind&lt;A, B&gt;(K&lt;Fin, A&gt; ma, Func&lt;A, K&lt;Fin, B&gt;&gt; f) =&gt;
        ma switch
        {
            Succ&lt;A&gt; (var x) =&gt; f(x),
            Fail&lt;A&gt; (var e)=&gt; new Fail&lt;B&gt;(e)
        };

    public static K&lt;Fin, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Fin, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Fin, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Succ&lt;A&gt;(value);

    public static K&lt;Fin, B&gt; Apply&lt;A, B&gt;(K&lt;Fin, Func&lt;A, B&gt;&gt; mf, K&lt;Fin, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}</code></pre><h3 id="validationf-a">Validation&lt;F, A&gt;</h3><blockquote><strong>Effect:</strong> Early termination of computation when in a <code>Fail</code> state and multiple fail-value aggregation when using applicative <code>Apply</code>.</blockquote><p>The main difference between <code>Either&lt;L, R&gt;</code> and <code>Validation&lt;F, A&gt;</code> is that <code>F</code> is constrained to be a monoid and that allows us to collect the errors in <code>Apply</code> (see the previous article on validation):</p><pre><code class="language-csharp">// Validation data-type
public abstract record Validation&lt;F, A&gt; : K&lt;Validation&lt;F&gt;, A&gt;
    where F : Monoid&lt;F&gt;;

public record Succ&lt;F, A&gt;(A Value) : Validation&lt;F, A&gt;
    where F : Monoid&lt;F&gt;;

public record Fail&lt;F, A&gt;(F Value) : Validation&lt;F, A&gt;
    where F : Monoid&lt;F&gt;;

// Validation trait implementation
public class Validation&lt;F&gt; : Monad&lt;Validation&lt;F&gt;&gt;
    where F : Monoid&lt;F&gt;
{
    public static K&lt;Validation&lt;F&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;Validation&lt;F&gt;, A&gt; ma, Func&lt;A, K&lt;Validation&lt;F&gt;, B&gt;&gt; f) =&gt;
        ma switch
        {
            Succ&lt;F, A&gt;(var r)  =&gt; f(r),
            Fail&lt;F, A&gt; (var x) =&gt; new Fail&lt;F, B&gt;(x) // carries the error through
        };

    public static K&lt;Validation&lt;F&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Validation&lt;F&gt;, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Validation&lt;F&gt;, R&gt; Pure&lt;R&gt;(R value) =&gt;
        new Succ&lt;F, R&gt;(value);

    public static K&lt;Validation&lt;F&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;Validation&lt;F&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;Validation&lt;F&gt;, A&gt; ma) =&gt;
        (mf, ma) switch
        {
            (Succ&lt;F, Func&lt;A, B&gt;&gt; (var f),  Succ&lt;F, A&gt; (var a))  =&gt; new Succ&lt;F, B&gt;(f(a)),
            (Fail&lt;F, Func&lt;A, B&gt;&gt; (var e1), Fail&lt;F, A&gt; (var e2)) =&gt; new Fail&lt;F, B&gt;(e1 + e2), // aggregates errors
            (Fail&lt;F, Func&lt;A, B&gt;&gt; (var e),  _)                   =&gt; new Fail&lt;F, B&gt;(e),
            (_,                            Fail&lt;F, A&gt; (var e))  =&gt; new Fail&lt;F, B&gt;(e),
        };
}</code></pre><h3 id="trya">Try&lt;A&gt;</h3><blockquote><strong>Effect: </strong>Early termination on an exception. Catches exceptions and turns them into a data-type that is part of the co-domain. Purifying the exception machinery!</blockquote><pre><code class="language-csharp">// Try data-type
public record Try&lt;A&gt;(Func&lt;A&gt; runTry) : K&lt;Try, A&gt;;

// Try extensions
public static class TryExtensions
{
    public static Try&lt;A&gt; As&lt;A&gt;(this K&lt;Try, A&gt; ma) =&gt;
        (Try&lt;A&gt;)ma;

    // Run without catching the exception
    public static A RunUnsafe&lt;A&gt;(this K&lt;Try, A&gt; ma) =&gt;
        ma.As().runTry();

    // Run and catch the exception
    public static Fin&lt;A&gt; Run&lt;A&gt;(this K&lt;Try, A&gt; ma)
    {
        try
        {
            return new Succ&lt;A&gt;(ma.As().runTry());
        }
        catch (Exception e)
        {
            return new Fail&lt;A&gt;(e);
        }
    }
}

// Try traits
public class Try : Monad&lt;Try&gt;
{
    public static K&lt;Try, B&gt; Bind&lt;A, B&gt;(K&lt;Try, A&gt; ma, Func&lt;A, K&lt;Try, B&gt;&gt; f) =&gt;
        new Try&lt;B&gt;(() =&gt; f(ma.RunUnsafe()).RunUnsafe());

    public static K&lt;Try, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Try, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Try, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Try&lt;A&gt;(() =&gt; value);

    public static K&lt;Try, B&gt; Apply&lt;A, B&gt;(K&lt;Try, Func&lt;A, B&gt;&gt; mf, K&lt;Try, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}
</code></pre><h3 id="iterablea">Iterable&lt;A&gt;</h3><blockquote><strong>Effect</strong>: Iterate multiple items. Early termination if there the collection yields no values.</blockquote><p>This is the first collection type that we&apos;ve implemented as a monad.  It&apos;s worth looking at how the <code>Bind</code> function is just nested <code>foreach</code> loops &#x2013; which means its equivalent of the <code>Option</code> early-out mechanism would be to bind with an empty collection.  Indeed we can imagine <code>Option</code> being a &apos;collection&apos; of <code>0</code> or <code>1</code> items.</p><p><code>Iterable</code> is a new data-type in language-ext that is a wrapper for <code>IEnumerable</code> &#x2013; it&apos;s everything that <code>IEnumerable</code> is but with traits.  </p><pre><code class="language-csharp">// Iterable data-type
public record Iterable&lt;A&gt;(IEnumerable&lt;A&gt; Items) : K&lt;Iterable, A&gt;, IEnumerable&lt;A&gt;
{
    public IEnumerator&lt;A&gt; GetEnumerator() =&gt;
        Items.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() =&gt;
        Items.GetEnumerator();
}

// Iterable extensions
public static class IterableExtensions
{
    public static Iterable&lt;A&gt; As&lt;A&gt;(this K&lt;Iterable, A&gt; ma) =&gt;
        (EnumerableM&lt;A&gt;)ma;
}

// Iterable trait implementation
public class EnumerableM : Monad&lt;EnumerableM&gt;
{
    public static K&lt;Iterable, B&gt; Bind&lt;A, B&gt;(K&lt;Iterable, A&gt; ma, Func&lt;A, K&lt;Iterable, B&gt;&gt; f)
    {
        return new Iterable&lt;B&gt;(Go());
        
        IEnumerable&lt;B&gt; Go()
        {
            foreach (var x in ma.As())
            {
                foreach (var y in f(x).As())
                {
                    yield return y;
                }
            }
        }
    }

    public static K&lt;Iterable, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Iterable, A&gt; ma)
    {
        return new Iterable&lt;B&gt;(Go());
        
        IEnumerable&lt;B&gt; Go()
        {
            foreach (var x in ma.As())
            {
                yield return f(x);
            }
        }
    }

    public static K&lt;Iterable, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Iterable&lt;A&gt;([value]);

    public static K&lt;Iterable, B&gt; Apply&lt;A, B&gt;(K&lt;Iterable, Func&lt;A, B&gt;&gt; mf, K&lt;Iterable, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}
</code></pre><h3 id="readerenv-a">Reader&lt;Env, A&gt;</h3><blockquote><strong>Effect: </strong>Carries an &apos;environment&apos; through the computation that can be accessed at any time without having to explicitly augment every function with an <code>Env environment</code> argument.</blockquote><p>This is very similar to the <code>IO&lt;A&gt;</code> monad from the last article.  It wraps up a <code>Func</code> making it lazy.  When invoked with an <code>Env</code> it runs the computation threading the environment through.</p><pre><code class="language-csharp">// Reader data-type
public record Reader&lt;Env, A&gt;(Func&lt;Env, A&gt; runReader) : K&lt;Reader&lt;Env&gt;, A&gt;;

// Reader extensions
public static class ReaderExtensions
{
    public static Reader&lt;Env, A&gt; As&lt;Env, A&gt;(this K&lt;Reader&lt;Env&gt;, A&gt; ma) =&gt;
        (Reader&lt;Env, A&gt;)ma;
    
    public static A Run&lt;Env, A&gt;(this K&lt;Reader&lt;Env&gt;, A&gt; ma, Env env) =&gt;
        ma.As().runReader(env);
}

// Reader trait implementations
public class Reader&lt;Env&gt; : Monad&lt;Reader&lt;Env&gt;&gt;
{
    public static K&lt;Reader&lt;Env&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;Reader&lt;Env&gt;, A&gt; ma, Func&lt;A, K&lt;Reader&lt;Env&gt;, B&gt;&gt; f) =&gt;
        new Reader&lt;Env, B&gt;(env =&gt; f(ma.Run(env)).Run(env));
    
    public static K&lt;Reader&lt;Env&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Reader&lt;Env&gt;, A&gt; ma) =&gt;
        new Reader&lt;Env, B&gt;(env =&gt; f(ma.Run(env)));

    public static K&lt;Reader&lt;Env&gt;, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Reader&lt;Env, A&gt;(_ =&gt; value);

    public static K&lt;Reader&lt;Env&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;Reader&lt;Env&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;Reader&lt;Env&gt;, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}

// Reader module
public static class Reader
{
    // Gets the environment out of the Reader and maps it 
    public static Reader&lt;Env, A&gt; asks&lt;Env, A&gt;(Func&lt;Env, A&gt; f) =&gt;
        new (f);

    // Gets the environment out of the Reader 
    public static Reader&lt;Env, Env&gt; ask&lt;Env&gt;() =&gt;
        asks&lt;Env, Env&gt;(identity);
}
</code></pre><h3 id="writerout-a">Writer&lt;Out, A&gt;</h3><blockquote><strong>Effect: </strong>Produces an output log alongside the monad result value (aka the bound value).</blockquote><p>This implementation takes an input argument (like <code>Reader</code>) and produces an additional output value (the log).  There&apos;s an alternative approach to implementing this that doesn&apos;t need the input argument, but it&apos;s usually less efficient due to the need to concatenate collections in the <code>Bind</code> function &#x2013; this approach only needs to concatenate in the <code>tell</code> function (which is just appending a single item).</p><p>Again note, this requires <code>Out</code> to be a monoid &#x2013; it means we can create an <code>Empty</code> log and use the <code>+</code> operator to append new output values.</p><pre><code class="language-csharp">// Writer data-type
public record Writer&lt;Out, A&gt;(Func&lt;Out, (A Value, Out Output)&gt; runWriter) : K&lt;Writer&lt;Out&gt;, A&gt;
    where Out : Monoid&lt;Out&gt;;

// Writer extensions
public static class WriterExtensions
{
    public static Writer&lt;Out, A&gt; As&lt;Out, A&gt;(this K&lt;Writer&lt;Out&gt;, A&gt; ma) 
        where Out : Monoid&lt;Out&gt; =&gt;
        (Writer&lt;Out, A&gt;)ma;
    
    public static (A Value, Out Output) Run&lt;Out, A&gt;(this K&lt;Writer&lt;Out&gt;, A&gt; ma)
        where Out : Monoid&lt;Out&gt; =&gt;
        ma.Run(Out.Empty);
    
    public static (A Value, Out Output) Run&lt;Out, A&gt;(this K&lt;Writer&lt;Out&gt;, A&gt; ma, Out output)
        where Out : Monoid&lt;Out&gt; =&gt;
        ma.As().runWriter(output);
}

// Writer trait implementations
public class Writer&lt;Out&gt; : Monad&lt;Writer&lt;Out&gt;&gt;
    where Out : Monoid&lt;Out&gt;
{
    public static K&lt;Writer&lt;Out&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;Writer&lt;Out&gt;, A&gt; ma, Func&lt;A, K&lt;Writer&lt;Out&gt;, B&gt;&gt; f) =&gt;
        new Writer&lt;Out, B&gt;(log =&gt;
        {
            var (value, log1) = ma.Run(log);  // threads the log through
            return f(value).Run(log1);        // runs with the updated log
        });

    public static K&lt;Writer&lt;Out&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Writer&lt;Out&gt;, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;Writer&lt;Out&gt;, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Writer&lt;Out, A&gt;(log =&gt; (value, log));

    public static K&lt;Writer&lt;Out&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;Writer&lt;Out&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;Writer&lt;Out&gt;, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}

// Writer module
public static class Writer
{
    // Writes a value to the output  
    public static Writer&lt;Out, Unit&gt; tell&lt;Out&gt;(Out item) 
        where Out : Monoid&lt;Out&gt; =&gt;
        new (log =&gt; (default, log + item));
}
</code></pre><h3 id="states-a">State&lt;S, A&gt;</h3><blockquote><strong>Effect:</strong> Threads a state-value through the computation.  It&apos;s a little bit like the <code>Reader</code> monad except the state isn&apos;t read-only: it can be updated.  Again, it removes the need to provide and additional <code>S state</code> argument and a tuple <code>(S, ...)</code> return value for every function that manages state.</blockquote><p>Note how the <code>Bind</code> function is almost a carbon copy of the <code>Bind</code> function for <code>Writer</code>.  In fact they&apos;re basically the same monad, just <code>Writer</code> has constraints where its state must be a monoid and has the <code>tell</code> function which knows how to append items &#x2013; but they&apos;re basically the same type.</p><pre><code class="language-csharp">// State data-type
public record State&lt;S, A&gt;(Func&lt;S, (A Value, S State)&gt; runState) : K&lt;State&lt;S&gt;, A&gt;;

// State extensions
public static class StateExtensions
{
    public static State&lt;S, A&gt; As&lt;S, A&gt;(this K&lt;State&lt;S&gt;, A&gt; ma) =&gt; 
        (State&lt;S, A&gt;)ma;
    
    public static (A Value, S State) Run&lt;S, A&gt;(this K&lt;State&lt;S&gt;, A&gt; ma, S state) =&gt;
        ma.As().runState(state);
}

// State trait implementations
public class State&lt;S&gt; : Monad&lt;State&lt;S&gt;&gt;
{
    public static K&lt;State&lt;S&gt;, B&gt; Bind&lt;A, B&gt;(K&lt;State&lt;S&gt;, A&gt; ma, Func&lt;A, K&lt;State&lt;S&gt;, B&gt;&gt; f) =&gt;
        new State&lt;S, B&gt;(state =&gt;
        {
            var (value, state1) = ma.Run(state); // threads the state through
            return f(value).Run(state1);         // runs with the updated state
        });

    public static K&lt;State&lt;S&gt;, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;State&lt;S&gt;, A&gt; ma) =&gt;
        ma.Bind(x =&gt; Pure(f(x)));

    public static K&lt;State&lt;S&gt;, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new State&lt;S, A&gt;(state =&gt; (value, state));

    public static K&lt;State&lt;S&gt;, B&gt; Apply&lt;A, B&gt;(K&lt;State&lt;S&gt;, Func&lt;A, B&gt;&gt; mf, K&lt;State&lt;S&gt;, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}

// State module
public static class State
{
    // Gets the state value and maps it  
    public static State&lt;S, A&gt; gets&lt;S, A&gt;(Func&lt;S, A&gt; f) =&gt; 
        new (state =&gt; (f(state), state));
    
    // Gets the state value   
    public static State&lt;S, S&gt; get&lt;S&gt;() =&gt; 
        gets&lt;S, S&gt;(identity);
    
    // Updates the monad&apos;s state value   
    public static State&lt;S, Unit&gt; put&lt;S&gt;(S value) =&gt; 
        new (state =&gt; (default, state));
}
</code></pre><h3 id="recap">Recap</h3><p>That&apos;s a lot of the core capabilities of language-ext in a single article!  </p><p>We&apos;ve seen so far:</p><ul><li>Alternative value monads:<ul><li><code>Maybe&lt;A&gt;</code> (equivalent of <code>Option&lt;A&gt;</code>) &#x2013; that has an alternative value of <code>None</code></li><li><code>Either&lt;L, R&gt;</code> &#x2013; that has a bespoke alternative value: <code>L</code></li><li><code>Fin&lt;A&gt;</code> &#x2013; equivalent to <code>Either&lt;Error, A&gt;</code> </li><li><code>Validation&lt;F, A&gt;</code> &#x2013; that has a bespoke monoidal alternative value <code>F</code> that collects multiple alternative results</li><li><code>Try&lt;A&gt;</code> - has an alternative value of <code>Error</code> which is used to catch exceptions and make them declarative.</li></ul></li><li>Collection monads<ul><li><code>Iterable</code> &#x2013; works with many values </li><li><em>Others not included as they&apos;re all implemented in a very similar way</em></li></ul></li><li>State and environment monads<ul><li><code>Reader&lt;Env, A&gt;</code> &#x2013; threads an environment value (often configuration) through the computation.  This is also a good way to do dependency injection with pure FP (either attach an interface to the environment or have member <code>Func</code> properties).</li><li><code>Writer&lt;Out, A&gt;</code> &#x2013; threads a monoidal output log through the computation.</li><li><code>State&lt;S, A&gt;</code> &#x2013; threads a state value through the computation and allows it to be updated, giving state mutation-like capabilities (in a pure way).</li></ul></li><li>Side effect monads<ul><li><code>IO&lt;A&gt;</code> &#x2013;  for managing world changing side-effects (previous article) </li><li><code>Eff&lt;A&gt;</code> &#x2013; <em>not included as it requires a bit more explanation (next article)</em></li></ul></li></ul><p>Some other monads we didn&apos;t cover here:</p><ul><li><code>Free&lt;F, A&gt;</code> &#x2013; which allows for any functor to be turned into a monad <em>for free</em>.</li><li><code>Cont&lt;A&gt;</code> &#x2013; continuations</li><li><code>Identity&lt;A&gt;</code> &#x2013; manages no effects at all!</li><li>Other collections like: <code>Seq&lt;A&gt;</code>, <code>Arr&lt;A&gt;</code>, <code>Lst&lt;A&gt;</code>, <code>Set&lt;A&gt;</code>, <code>HashSet&lt;A&gt;</code></li></ul><p>We&apos;ll cover those in a later article because they&apos;re either too hard to cover quickly (<code>Free</code> monad) or really need some context from what&apos;s coming in the next article.</p><h3 id="composition">Composition</h3><p>Hopefully it should be fairly clear that these things are not super hard to make.  Sure, if you&apos;re new to this, it might still be turning your head inside out a little, but the actual quantity of code you need to write to make these work is pretty minimal.</p><blockquote><em><strong>Remember:</strong> All of the types above will work with LINQ straightaway &#x2013; there&apos;s no additional support code needed.</em></blockquote><p>The single biggest issue is that these monads are all <em>single-feature </em>monads.  What if you want to combine optional-behaviour (<code>Option&lt;A&gt;</code>) and side-effects (<code>IO&lt;A&gt;</code>)? </p><p>You can&apos;t.  </p><p>A monadic expression can only work with one type at a time (you can&apos;t combine <code>IO</code> and <code>Option</code> in a single expression, for example) and that&apos;s a serious limitation.  So serious in fact that in previous versions of language-ext I had the following (now removed) monads:</p><ul><li><code>OptionAsync&lt;A&gt;</code> &#x2013; <code>Option</code> and <code>IO</code></li><li><code>EitherAsync&lt;A&gt;</code> &#x2013; <code>Either</code> and <code>IO</code></li><li><code>TryAsync&lt;A&gt;</code> &#x2013; <code>Try</code> and <code>IO</code></li><li><code>TryOption&lt;A&gt;</code> &#x2013; <code>Try</code> and <code>Option</code></li><li><code>TryOptionAsync&lt;A&gt;</code> &#x2013; <code>Try</code>, <code>Option</code>, and <code>IO</code>.</li></ul><p>These were all manually written compositions of the other monadic types.  But, as we create more types, the combinations explode.  What if you want to combine the capabilities of 3 or 4 monads?!</p><p>Luckily, in <code>v5</code> of language-ext we have a solution to that, <strong>Monad Transformers</strong>. They allow us to compose existing monads into <em>super-monads!!!  </em></p><p><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-9-monad-transformers/"><em>Part 9 Monad Transformers...</em></a></p>]]></content:encoded></item><item><title><![CDATA[Are higher-kinds in C# real?]]></title><description><![CDATA[A small diversion into the social media comments made about the higher-kinds approach used in language-ext.]]></description><link>https://paullouth.com/are-higher-kinds-in-csharp-real/</link><guid isPermaLink="false">662f55772ac0342e8bc943f0</guid><category><![CDATA[csharp]]></category><category><![CDATA[hkt]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[language-ext]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Mon, 29 Apr 2024 10:49:40 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/04/Are-higher-kinds-in-C--real.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/04/Are-higher-kinds-in-C--real.png" alt="Are higher-kinds in C# real?"><p>In a recent <a href="https://twitter.com/markrendle/status/1784227529907175531?ref=paullouth.com">Twitter semi flame-war</a> I encountered some opposition to the idea that the <a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">approach to higher-kinds</a> used in <a href="https://github.com/louthy/language-ext?ref=paullouth.com">language-ext</a> is a valid approach.  In the end I decided to back out of it, because nothing is solved on Twitter, but I felt I needed to add enough context so those who follow me on Twitter can at least judge for themselves.</p><p>In this article I want to <em>prove</em> that <code>f a</code> in Haskell is equal (up to isomorphism) with <code>K&lt;F, A&gt;</code> in C#.</p><p>To do this we need to build our own type system.  It needs to follow the extended lambda calculus approach used by the likes of Haskell and other FP languages.  Then, we need to augment it, so that we can represent generic-types the way that C# does it.  If we can transform Haskell style higher-rank polymorphic representations to C# generics and back again (without losing any fidelity), we have a proof.</p><p>To make a simple type system we need:</p><ul><li>Primitive types (<code>int</code>, <code>string</code>, etc.)</li><li>Type variables (like the <code>A</code> in <code>Option&lt;A&gt;</code>)</li><li>Type names (like the <code>Option</code> in <code>Option&lt;A&gt;</code>)</li><li>Lambda abstractions</li><li>Type applications</li></ul><p>The last two items need a little explanation...  </p><p><strong>Lambda abstractions</strong> are like lambdas in any programming language except they&apos;re in the type system and are &apos;run&apos; at compile time.  The &apos;running&apos; of the lambdas should (by the end of the compilation) generate concrete types.  Lambda abstractions follow lambda calculus in that they accept single arguments only.  Multiple arguments are achieved by nesting multiple lambdas.  </p><p><strong>Type applications</strong> are what&apos;s used to invoke the lambda abstractions (passing an argument to evaluate).  They can apply a single argument to a single lambda.  So applying multiple arguments to nested lambdas needs multiple type applications.  This also means you can <em>partially apply</em> arguments.  By example: <code>Option&lt;int&gt;</code> is <em>applying</em> the <code>int</code> type to the <code>Option</code> lambda-abstraction. </p><p>First, we need a base type: <code>Ty</code>:</p><pre><code class="language-csharp">public abstract record Ty;</code></pre><p>Then a primitive type to define all the supported primitives:</p><pre><code class="language-csharp">public enum Prim
{
    Int,
    String,
    Bool
}

public record TyPrim(Prim Value) : Ty;</code></pre><p>Type variables:</p><pre><code class="language-csharp">public record TyVar(string Name) : Ty;
</code></pre><p>Type names for concrete types:</p><pre><code class="language-csharp">public record TyName(string Name) : Ty;
</code></pre><p>Lambda abstractions:</p><pre><code class="language-csharp">public record TyLambda(string VarName, Ty Body) : Ty;</code></pre><p>You should recognise the pattern from lambdas in languages that support them: a letter defining the variable-name of the argument and a body-expression.  The idea is that when an argument is applied to the lambda the instances of <code>TyVar(VarName)</code> in <code>Body</code> are replaced with the applied type.</p><p>Type application:</p><pre><code class="language-csharp">public record TyApply(Ty LamdbaAbs, Ty Arg) : Ty;</code></pre><p>The first argument should evaluate to a <code>TyLambda</code> and the second argument is the value to pass to the lambda as its parameter.</p><p>We can also make construction of these types a little easier by adding some static functions  to <code>Ty</code>:</p><pre><code class="language-csharp">public record Ty
{
    public static readonly TyPrim Int = new(Prim.Int);
    public static readonly TyPrim String = new(Prim.String);
    public static readonly TyPrim Bool = new(Prim.Bool);
    public static TyVar Var(string name) =&gt; new(name);
    public static TyName Named(string name) =&gt; new (name);
    public static TyLambda Lambda(string varName, Ty body) =&gt; new(varName, body);
    public static TyApply Apply(Ty lambda, Ty arg) =&gt; new(lambda, arg);
}</code></pre><p>That&apos;s all of the basics we need for the moment.  </p><p>So, something like <code>f a</code> in Haskell would (in its type-system) look like this:</p><pre><code class="language-csharp">Ty.Apply(Ty.Var(&quot;f&quot;), Ty.Var(&quot;a&quot;))</code></pre><p>Which, when evaluated, will look up <code>f</code> (which it expects to be a <code>TyLambda</code>) and then substitute the evaluated <code>a</code> for <code>VarName</code> in the lambda body.  And so, this is how Haskell (and most FP languages) does polymorphism (generics).  C# doesn&apos;t represent generic types as lambdas, which presumably is why higher-rank polymorphism isn&apos;t a thing in C#.</p><p>Let&apos;s take a look at my solution for higher-rank polymorphism in C#.  It is primarily enabled by a single type: <code>K&lt;F, A&gt;</code>.  My argument is that <code>K&lt;F, A&gt;</code> is equal up to isomorphism to <code>f a</code> in Haskell.</p><p>What does &quot;equal up to isomorphism&quot; mean?  It means there&apos;s a way of transforming one type to the other type and back again without losing any fidelity.  So, they&apos;re not <em>equal</em> because they&apos;re made of different components, but they&apos;re convertible back&apos;n&apos;forth and so they&apos;re <em>equal up to isomorphism</em>.  Which is a slightly weaker statement about equality, but they&apos;re functionally equal because we can make one from the other.</p><p><code>K&lt;F, A&gt;</code> can&apos;t be directly represented with the type-system we have created.  Let&apos;s ignore the <code>K</code> part  &#x2013; it is genuinely irrelevant to this discussion, it&apos;s just a label &#x2013; there are no members in the <code>K</code> type, so the only thing that matters is the <code>&lt;F, A&gt;</code> part.  The <code>&lt;F, A&gt;</code> part is a <em>tuple</em> of types.  So, let&apos;s add <code>TyTuple</code> to our type system:</p><pre><code class="language-csharp">public record TyTuple(Seq&lt;Ty&gt; Items) : Ty;</code></pre><p>A tuple is zero or more types.  Let&apos;s have some friendly constructors functions in <code>Ty</code>:</p><pre><code class="language-csharp">public static TyTuple Tuple(Seq&lt;Ty&gt; items) =&gt; new (items);
public static TyTuple Tuple(params Ty[] items) =&gt; new (toSeq(items));
</code></pre><p>We can now represent <code>K&lt;F, A&gt;</code> or really <code>&lt;F, A&gt;</code> in our type system:</p><pre><code class="language-csharp">Ty.Tuple(Ty.Var(&quot;f&quot;), Ty.Var(&quot;a&quot;));</code></pre><p>So, to prove the isomorphism between <code>f a</code> and <code>&lt;F, A&gt;</code> we need to be able to convert between their type-system representations without losing anything in the process.</p><p>Let&apos;s create a <code>K</code> type as it is in C# (I&apos;m using <code>Option&lt;int&gt;</code> to make it a bit more interesting):</p><pre><code class="language-csharp">var kOptionInt = Ty.Tuple(Ty.Named(&quot;Option&quot;), Ty.Int);  // Option&lt;int&gt;</code></pre><p>From that, can we create the <code>Ty.Apply</code> version?  Yes, we can...</p><pre><code class="language-csharp">var optionInt = Ty.Apply(kOptionInt.Items[0], kOptionInt.Items[1]);</code></pre><p>To prove the isomorphism we need to back able to go back and prove the types are the same...</p><pre><code class="language-csharp">var kOptionInt2 = Ty.Tuple(optionInt.LamdbaAbs, optionInt.Arg);

Console.WriteLine(kOptionInt == kOptionInt2); // True</code></pre><p>It outputs <code>True</code> and so proves we can convert one way and back again.  Let&apos;s, for completeness, start with <code>Ty.Apply</code> and convert to <code>Ty.Tuple</code> and back again:</p><pre><code class="language-csharp">var optionInt = Ty.Apply(Ty.Named(&quot;Option&quot;), Ty.Int);
var kOptionInt = Ty.Tuple(optionInt.LamdbaAbs, optionInt.Arg);
var optionInt2 = Ty.Apply(kOptionInt.Items[0], kOptionInt.Items[1]);

Console.WriteLine(optionInt == optionInt2); // True
</code></pre><p>That also outputs <code>True</code> &#x2013; they&apos;re equal up to isomorphism and we&apos;ve proved it.</p><blockquote>To take this proof further we can build the evaluator for the types and prove that the evaluated types are equal (up to isomorphism).  I will do that if this article gets some push-back, but I already know the answer.</blockquote><p>So, it doesn&apos;t matter what the purists say.  The language-ext approach to higher-kinds is the same as the approach in Haskell and any other language with higher rank polymorphism.  Yes, we need an additional type to represent the partially applied type (for example, <code>IO</code> for the <code>IO&lt;A&gt;</code>), but that doesn&apos;t matter as we only attach the trait implementation to that &apos;partially applied&apos; type.  That&apos;s not much different to having separate types for the class <code>instance</code> definitions in Haskell &#x2013; in fact I&apos;d argue they&apos;re also isomorphic.</p><p>I do feel there&apos;s often a snobbishness about those of us who are doing functional programming in C#.  The arguments are nearly always based around some bullshit academic reasoning not related to solving the problem but purely to be a position to sneer from.  It adds nothing.  Or we get something like &quot;why do it in C# in the first place, when there are better languages around?&quot; &#x2013; which is always a naive statement to make.</p><blockquote>By the way, I have no issue with academics or the pursuit of knowledge through academia.  The whole of language-ext is standing on academic shoulders.  But the unwillingness to accept other practical solutions to problems and then the inevitable sneering is tiring and unnecessary.  C# can achieve every aspect of higher-kinded traits using its type-system.  No hacks, no reflection, no dynamic references.  Purely with its type-system &#x2013; that should be the end of the discussion.</blockquote><p>Haskell (the poster-child for pure functional programming) has many problems also.  I led a team doing a pure Haskell project two years ago.  It was the first time I&apos;d used Haskell in a professional setting &#x2013; I&apos;ve used it on and off for many years on personal projects, just never professionally.  The major problems I encountered were:</p><ul><li>The open-source library ecosystem is poor:  <ul><li>Lots of unmaintained and incomplete projects for critical functions</li><li>Lots of amateurish solutions (again, for critical functions) &#x2013; I put this down to the Haskell world being full of academics and not professional engineers.</li><li>We ended up building our own libraries of things you&apos;d normally take off-the-shelf in other ecosystems.  As a leader seeing time eaten up this way is tough.</li></ul></li><li>The more junior devs in my team had a really hard time with the language.  These devs had worked with language-ext for years, so it&apos;s not like they had no exposure to pure functional programming, but for some reason they struggled.  In parallel to this we&apos;d even done a weekly &apos;Haskell book club&apos; to get everyone up to speed and to encourage discussion &#x2013; but it didn&apos;t really move the needle.</li><li>The tooling, although much better than it was when I first learned Haskell, is still poor.  The compiler is slow.  It tends to exit on the first error and then produce other spurious errors. The debugging story was extremely poor (I suspect this was the main issue for juniors struggling).  Even random things like the auto-formatting engine we were using just stop being supported. And the plugins to VSCode seem to be endlessly buggy.</li></ul><p>Luckily, as a co-founder of the company, I was able to weather the relatively slow progress of the project: I understood that the code was likely to be more robust and would need less maintenance and so a slower initial phase of the project could be caught up later.  </p><p>However, after a year we decided to can the project.  It was a business decision not related to Haskell, so I won&apos;t claim it was the cause of the canning, but based on my experience I will probably never start a greenfield project with Haskell again.  </p><p>Don&apos;t get me wrong, I still love the language, it has directly influenced much of language-ext, but the ecosystem is weak &#x2013; which, after 30 years of Haskell&apos;s existence, probably means it&apos;s not likely to get much stronger.</p><p>The reality is C# is used by more people than Haskell.  The library ecosystem is mature.  C# for all its problems has world-class tooling.  The compiler is probably second to none.  The IDEs (Visual Studio or Rider) are second to none.  <em>There are probably more people doing functional programming in C# than in the entire Haskell community.</em>  These are things to not take lightly when choosing a language to build substantial projects with.</p><p>Don&apos;t we deserve higher-kinds?  Aren&apos;t we allowed to follow the pure functional programming paradigm?  </p><p>I think we are.</p><hr><p>As expected a flame war started as soon as I posted this to Twitter (I mean, like within minutes!)</p><p>Anyway, I&apos;m opting out again, because the arguments are circular and going nowhere.  But, the whole point of this post was to ease the mind of those stepping into this world for the first time &#x2013; it wasn&apos;t to make lambda calculus obsessives happy.  So, I&apos;ll cover some of the &quot;issues&quot; raised and then leave it as that:</p><ol><li><em>&quot;As for your proof, here is a simple counter-example. In C# the following instantiation of type variables is legal: <code>K&lt;String, Int&gt;</code>. In Haskell &apos;String Int&apos; fails to type check (exactly because there is simply no notion of kinds in C#)&quot;</em></li></ol><p>There are kinds in C#, we have generics, so we have kinds &#x2013; we just can&apos;t use type-variables as the first part of the <code>* -&gt; *</code> arrow (meaning we can&apos;t parameterise the <code>F</code> in  <code>F&lt;A&gt;</code>).  </p><p><code>K&lt;string, int&gt;</code> is legal in C# but it has no use for implementing traits.  That doesn&apos;t make the approach invalid.  The argument that it <em>should</em> be invalid is arguing that the first parameter (<code>string</code>) should be a lambda-abstraction.  But it doesn&apos;t need to be in the tuple based approach to implementing higher-kinds, because we&apos;re not using lambda-abstractions, and we&apos;re not using lambda-abstractions because we&apos;re using tuples, ...  So, the argument is a pointless circular one. It&apos;s basically saying &quot;It&apos;s not implemented like Haskell, therefore it&apos;s not valid&quot; which isn&apos;t a good argument.</p><p>However, stating that <code>IO</code> as the first argument (for example) is a <code>* -&gt; *</code> kind in Haskell and a <code>*</code> kind in C# does require a little more explanation.  The isomorphism works in the type-system I invented <strong>in this article</strong>.  The isomorphism doesn&apos;t work in Haskell or C# &#x2013; Haskell doesn&apos;t have tuple types and C# doesn&apos;t have lambda-abstractions &#x2013; so this proof can&apos;t be run in either language.  </p><p>My primary point with the proof above was that a 2-tuple and a type-application are isomorphic.  </p><p>I realise that&apos;s not the most profound proof to ever be written, but it validates the approach of using the tuple-type <code>K&lt;F, A&gt;</code> to represent <code>F&lt;A&gt;</code>.  <code>F</code> isn&apos;t a lambda-abstraction because it doesn&apos;t need to be in our approach, we are able to resolve the relevant trait from the <code>*</code> type without the need for a partially applied value being passed as an argument to a trait-type.</p><p>Quite simply, we don&apos;t need lambda-abstractions to implement higher-kinded traits, which is lucky, because C# doesn&apos;t have them.</p><ol start="2"><li><em>&quot;No, Haskell does not encode HKTs. Its type system is directly based on lambda calculus, and LC is _the_ definition of kinds and types. There is no need to encode the definition when you (Haskell) are the &quot;native&quot; implementation of the definition.&quot;</em></li></ol><p>I love it when someone points out Haskell&apos;s implementation is done with lambda calculus as I state clearly in the article and I implemented the type-system using it!  Some people just like to score points on the internet I guess.  Perhaps it needs a new term: &apos;Lambdasplaining&apos; maybe?</p><ol start="3"><li><em>&quot;We can indeed see this HKT embedding as an alternative implementation, only in library space and not in the type system. It is not the same or equivalent to native support though and claim that C# supports HKTs.&quot;</em></li></ol><p>This is one of those &quot;you can&apos;t play with your toys because they&apos;re not as good as ours&quot; arguments.  It looks down on the implementation saying it&apos;s not &apos;native&apos;.  The only thing language-ext does is say: &quot;Let&apos;s use this type <code>K&lt;F, A&gt;</code> to represent higher-kinds&quot; &#x2013; but <code>K&lt;F, A&gt;</code> is still a C# type, it&apos;s not something magical hacked into the type system &#x2013; it introduces a convention, sure, but that&apos;s it.  Everything else is the C# type-system as-is.  There&apos;s no reflection, there&apos;s no cheating, all constraints are enforced by the C# type checker.  As it should be. <code>F</code> is not constrained to be a lambda-abstraction, because lambda-abstractions don&apos;t exist and we don&apos;t need them to implement higher-kinded traits.</p><ol start="4"><li><em>&quot;As you write yourself, C# allows and accepts only type variable of kind *. In particular not of kind * -&gt; *. No arrows, no HKTs. This is the definition of what it means to be a HKT and you can&apos;t promote an embedding to the real thing just by declaring them as equivalent.&quot;</em></li></ol><p>This argument is, yet again, arguing that only lambda-abstractions can encode higher-kinded types.  Yet, as we see, they can be encoded by other means.  The general crux of this poster&apos;s recursive responses is that &quot;it&apos;s not lambda calculus, so your approach isn&apos;t valid&quot;.  </p><p>My response is this: Alan Turing proved that his Turing Machine was equivalent to Lambda Calculus.  So, not every implementation has be in Lambda Calculus to be valid.  And, if you have a problem with that, take it up with Alan Turing.</p><hr><p><strong>Response from Erik Meijer</strong></p><p><em>&quot;Super cool hack, really; but an encoding does not imply it is usable. More importantly<br><br>&gt; Don&apos;t we deserve higher-kinds? Aren&apos;t we allowed to follow the pure functional programming paradigm?<br><br>Higher kinds does not give you pure functions</em><br><br><a href="https://queue.acm.org/detail.cfm?id=2611829&amp;ref=paullouth.com" rel="noopener noreferrer nofollow"><em>https://queue.acm.org/detail.cfm?id=2611829&#x2026;</em></a><br><br><em>If you are using C#, IMHO, it is best to stick with idiomatic C# instead of trying to bolt a pseudo Haskell style on top.<br><br>Don&apos;t fight the language, embrace it. Write baby code. KISS.&quot;</em></p><p>I have a lot of respect for Erik.  He brought LINQ to C# after all! He&apos;s one of the few people in the industry that I am always interested in hearing from, because even though his Twitter handle is @headinthebox, he really is someone who thinks outside of the box.  I would encourage you to look up his talks on YouTube as they&apos;re always thought provoking and usually pretty inspirational too.  </p><p>That doesn&apos;t mean I agree with him on everything though!</p><p>Before Erik wrote this response I already knew his position on this (because I&apos;ve watched his talks).  But let&apos;s break down what he&apos;s said:</p><blockquote><em>but an encoding does not imply it is usable</em></blockquote><p>Nobody knows yet whether this will be usable, because I have yet to release language-ext <code>v5</code>.  But, I&apos;ve been dog-fooding it myself, building a DB Layer for Foundation DB and I have to say, it feels pretty good!  The fact that this actually makes LINQ work like <code>do</code> notation in Haskell (i.e. once you implement the <code>Monad&lt;M&gt;</code> trait for your type, LINQ starts working), in my mind, finishes the job that should have been done by the C# team.  They stopped short of implementing monads in C# properly and instead opted for &apos;magic methods&apos; (<code>Select</code> and <code>SelectMany</code>) &#x2013; this was a colossal mistake in my humble opinion.  They should have at least committed to making a trait system to deal with the C# magic methods (all of them) if they weren&apos;t able to do it at the time.</p><blockquote><em>Higher kinds does not give you pure functions</em></blockquote><p>That wasn&apos;t what I was implying with the sentence I wrote.  So a small misunderstanding there.</p><blockquote><a href="https://queue.acm.org/detail.cfm?id=2611829&amp;ref=paullouth.com" rel="noopener noreferrer nofollow"><em>https://queue.acm.org/detail.cfm?id=2611829&#x2026;</em></a></blockquote><p>I&apos;d previously read &apos;The Curse of the Excluded Middle&apos; stating that &quot;Mostly functional&quot; programming doesn&apos;t work. Mostly.</p><p>I agree with the basic premise and go to great lengths in the <a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Monad article</a> to emphasise the importance of <em>everything</em> being pure functions.  However, I don&apos;t fully agree with Erik&apos;s position.</p><p>Let&apos;s say this was my program:</p><pre><code class="language-csharp">void Main()
{
   PureFunction().Run();
   ImpureFunction();
}</code></pre><p>If those functions represent (by some odd coincidence) half of your code base each (half pure, half impure).  Then you still benefit from the pure functional programming half.  So, you can start small and build up something that becomes progressively more stable.  Every block of pure code, even if surrounded by impure code, is one block you don&apos;t have to worry so much about. Is it fundamentalist programming?  Of course not.  But slowly building out from there pays you back each time you expand the scope of the pure code.  You won&apos;t have solved all of the worlds ills, but you&apos;ve made part of the world&apos;s ills better. Any pure function in an impure code-base is, by-definition: more robust, easier to compose, cacheable, parallelisable, etc. these are real benefits, doesn&apos;t matter how small you start.</p><p>I have direct experience of this, the project I ran from 2005 - 2023, which was a 10 million lines of code behemoth, started out imperative and OO.  It kept falling foul of the issues you get all of the time with mutable-state imperative applications (we were writing &apos;baby code&apos; as Erik calls it).  I looked for an alternative approach and that birthed language-ext.  Over time language-ext took over the application.  </p><p>Still today there are areas that are not pure, but there&apos;s a huge amount that is, and that code is easier maintain and extend than the impure parts.  So, you do get benefits, and you can progressively move over to pure FP.  Just remember, any impure function in a pure expression makes the whole thing impure &#x2013; so as devs we have to be strict with ourselves. </p><p>But, even in a language like Haskell there&apos;s a function called <code>unsafePerformIO</code> which breaks all of the purity guarantees of Haskell &#x2013; it doesn&apos;t show up in any function type-signature &#x2013; so you have no idea whether <em>any </em>of your code is pure.  By convention, people try not to do that, but they can.  It&apos;s the same in any other language, you have to be strict with yourself.  And, on a team, you have to have a good code-review process in place so impure code doesn&apos;t sneak into the pure bits of your code.  It requires a culture change within your team, everyone needs to understand <em>why</em> you&apos;re doing this.</p><p>Ultimately though, that&apos;s why language-ext is more of a &apos;base class library&apos; for FP in C#.  Because if you&apos;re going to do pure FP in C# then you&apos;re not going to get it by just adding an <code>Option</code> library to your app, you have to go all-in.  This library is intentionally breaking the idioms of C# to create a new community of functional-programmers within the C# set of devs.  Much like the sub-communities with Scala-land (although, hopefully without the infighting!)</p><blockquote><em>If you are using C#, IMHO, it is best to stick with idiomatic C# instead of trying to bolt a pseudo Haskell style on top.</em></blockquote><p>As I&apos;ve mentioned, I&apos;m breaking the idioms on purpose, there&apos;s room for two.  But, even with that said, I think the idioms of C# have moved quite far from where it was in <code>v1</code>.</p><p>Look at the new <code>INumber</code> type (which is the base interface for <code>Int32</code> etc.):</p><pre><code class="language-csharp">  public interface INumber&lt;TSelf&gt; : 
    IComparable,
    IComparable&lt;TSelf&gt;,
    IComparisonOperators&lt;TSelf, TSelf, bool&gt;,
    IEqualityOperators&lt;TSelf, TSelf, bool&gt;,
    IModulusOperators&lt;TSelf, TSelf, TSelf&gt;,
    INumberBase&lt;TSelf&gt;,
    IAdditionOperators&lt;TSelf, TSelf, TSelf&gt;,
    IAdditiveIdentity&lt;TSelf, TSelf&gt;,
    IDecrementOperators&lt;TSelf&gt;,
    IDivisionOperators&lt;TSelf, TSelf, TSelf&gt;,
    IEquatable&lt;TSelf&gt;,
    IIncrementOperators&lt;TSelf&gt;,
    IMultiplicativeIdentity&lt;TSelf, TSelf&gt;,
    IMultiplyOperators&lt;TSelf, TSelf, TSelf&gt;,
    ISpanFormattable,
    IFormattable,
    ISpanParsable&lt;TSelf&gt;,
    IParsable&lt;TSelf&gt;,
    ISubtractionOperators&lt;TSelf, TSelf, TSelf&gt;,
    IUnaryPlusOperators&lt;TSelf, TSelf&gt;,
    IUnaryNegationOperators&lt;TSelf, TSelf&gt;,
    IUtf8SpanFormattable,
    IUtf8SpanParsable&lt;TSelf&gt;
    where TSelf : INumber&lt;TSelf&gt;</code></pre><p>The .NET team, in their own especially wordy style, are also using this trait technique.  With <code>IAdditiveIdentity</code> and <code>IAdditionOperators</code> they are also embracing semigroups and monoids!  So, I&apos;m not sure this approach is really that far away from idiomatic C# any more.  </p><p>Of course, taking this a step further to implement more complex types like <code>Monad</code> and <code>Applicative</code> could be argued to be pushing that boundary a little, but the technique is the same really.</p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 7 - monads]]]></title><description><![CDATA[An introduction to one of the most powerful patterns in all of computer science: the monad!]]></description><link>https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/</link><guid isPermaLink="false">6629e5ed2ac0342e8bc93e4f</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[monad]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[hkt]]></category><category><![CDATA[traits]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Fri, 26 Apr 2024 15:02:33 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/05/monads-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/05/monads-1.png" alt="Higher Kinds in C# with language-ext [Part 7 - monads]"><p>This is a multi-part series of articles &#x2013; and you&apos;ll need to know much of what&apos;s in the earlier parts to follow this &#x2013; so it&apos;s worth going back to the earlier episodes if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li><li><a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">Part 6 - Traversables</a></li></ul><p>OK, this is the big one, the one we&apos;ve all been waiting for, yes, <strong><em>it&apos;s time to implement monads</em></strong>!</p><p>There&apos;s a bit of a meme in the dev community around the difficulty in explaining monads.  Do a search for &quot;Yet Another Monad Tutorial&quot; and you&apos;ll see what I mean! </p><p>Apparently, nobody has found a way to concisely or clearly describe monads to the average <em>non-monad-knowing</em> person.  There appears to be a &apos;thing&apos; where, once someone is confident with pure functional-programming, they forget how difficult/alien it seemed at first and because pure functional-programming is &#x2013; in many ways &#x2013; simpler than imperative programming, they lose all ability to put their minds back into that initial confused state.  </p><p>You may balk at the idea that pure functional-programming is simpler than imperative programming &#x2013; especially when it comes to the terms, like &apos;monad&apos;, &apos;functor&apos;, &apos;applicative&apos;, ... there&apos;s a feeling of &quot;I can&apos;t place these terms with real world concepts&quot;.  But, terminology aside, I have never felt more confident about my code as I have in the pure functional-programming era of my life.  I did ~15 years of procedural coding (BBC BASIC and C), ~15 years of OO coding (with C++ and C#), and have now done more than a decade of FP programming (C#, F#, Haskell, PureScript).  So, I feel I can confidently state that I have had enough experience to at least have an opinion on this!</p><p>I suspect I fall into the <em>&apos;fail to explain properly&apos;</em> trap sometimes too, it&apos;s probably impossible not to.  I re-read my <a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">last article</a> on the <code>Traversable</code> type and can&apos;t help but think that it needs some better exposition.  But, right now, I can&apos;t tell whether the <em>five</em> previous articles are enough for the reader to follow along &#x2013; it should be, but is it?</p><p>I promised myself I&apos;d never write a &apos;Yet Another Monad Tutorial&apos;.  But, because we now have the new <code>Monad&lt;M&gt;</code> trait in <a href="https://github.com/louthy/language-ext/?ref=paullouth.com">language-ext</a>, it probably needs some explanation!</p><h2 id="yet-another-monad-tutorial">Yet Another Monad Tutorial</h2><p>Something that is always missed in monad tutorials is &quot;why?&quot;.  Why do we even need monads?</p><p>First, we don&apos;t <em>need</em> them.  C# devs can manage perfectly fine without them.  But, what language-ext is all about is enabling <em>pure functional programming in C#.  </em>And, although monads aren&apos;t <em>needed</em> for pure functional programming, they make the life of the pure functional dev<em> easier</em>.  But, before I can explain why, let&apos;s just have a refresher on the whole pure functional programming &apos;<em>thing&apos;...</em></p><p>The basics of pure functional programming are this:</p><ol><li>Functions are values</li><li>Everything is an expression</li><li>All expressions are pure and/or have referential transparency</li></ol><p>Item 1, we know about, so that doesn&apos;t need explaining.  Item 2, &apos;Everything is an expression&apos; thing is interesting.  If everything is an expression then we don&apos;t have <a href="https://en.wikipedia.org/wiki/Statement_(computer_science)?ref=paullouth.com"><em>statements</em></a> &#x2013; no lines of code, just an expression-tree of code.  Expression trees are quite hard to mentally manage (as well as write), so we need to find a way of having lines-of-code that are still, somehow, expressions.</p><p>If you look at an ML based language, you might see some code like this:</p><pre><code class="language-fsharp">let x = doSomething () in
let y = doSomethingElse () in
x + y</code></pre><p>These look like statements in an imperative language, the temptation is to think the above is equivalent to:</p><pre><code class="language-csharp">var x = DoSomething();
var y = DoSomethingElse();
return x + y;</code></pre><p>But, in fact they&apos;re completely different.  The ML example gets rearranged by the compiler to be lambdas with invocations (everything is a function in functional programming!):</p><pre><code class="language-fsharp">(fun x -&gt; (fun y -&gt; x + y) DoSomethingElse()) DoSomething()</code></pre><p>That is how something that is an expression can end up looking like multiple statements.  </p><p>There is a real scoping difference &#x2013; even if they look exactly like regular statements.  The example above can be factored and reduced in a way that imperative statements can&apos;t (well, not without some serious analysis).</p><p>OK, so what?  Why should we care?  Well, we can now write expressions in an imperative way (which I think is probably more natural for us) without losing any of the benefits of expressions.  </p><p>Item 3: &quot;All expressions are pure and/or have referential transparency&quot; is the next thing we need in pure functional programming...</p><ul><li>A pure expression is either a primitive value or entirely constructed from other pure expressions.  The &apos;smallest&apos; pure expression is a value.  It should not produce any side-effects (no mutating global state, no writing to a file, etc.).</li><li>A pure function is one where the function body is a pure expression.  The only values the expression can depend on are those provided to the function as arguments (so, no references to global state).  That means the result of the function is entirely dependent on the inputs to the function.  </li><li>An expression that has referential transparency is almost exactly the same as a pure expression.  The main difference is that &apos;internally&apos; it may not be a pure expression (could be implemented as a <code>for</code> loop, for example), but on the &apos;outside&apos; it behaves in exactly the same way a pure expression behaves.  Namely that you could replace the expression with a value and the consequence of using it remains the same.</li></ul><p>There is a small problem though.  A requirement of both pure expressions and referentially transparent expressions is that we should be able to replace the expression with a value (because we expect the same result from evaluating the expression every single time).  But, for some expressions, that isn&apos;t true...</p><pre><code class="language-csharp">var now = DateTime.Now;</code></pre><p>Clearly, we can&apos;t replace the <code>DateTime.Now</code> expression with the first result we get and then use it forever more, otherwise the time will never change. <em> <code>DateTime.Now</code> is not pure.</em></p><p>So, if we&apos;re going to do pure functional programming, where <em>every single expression </em>is pure then we need a different approach.</p><p>You may think &quot;So what, this is C#, just use <code>DateTime.Now</code> and get over it?!&quot;.  That is certainly a valid approach.  But, you have to remember <em>why</em> we&apos;re doing pure functional programming in the first place:</p><ul><li>Fewer bugs: Pure functions, which have no side effects and depend only on their input parameters, are easier to reason about and test, leading to fewer bugs in the code-base.</li><li>Easier optimisation: Since pure functions do not have any side effects, they can be more easily optimised by the compiler or runtime system. This can lead to improved performance.</li><li>Faster feature addition: The lack of side effects and mutable state in pure functional programming makes it easier to add new features without introducing unintended consequences. This can lead to faster development cycles.</li><li>Improved code clarity: Pure functions are self-contained and independent, making the code more modular and easier to understand. This can improve code maintainability.</li><li>Parallelisation: Pure functions can be easily parallelised, as they do not depend on shared mutable state, which can lead to improved scalability.</li><li>Composition: This is the big one.  Only pure functional programming has truly effective composition.  Composition with <em>impure</em> components sums the impurities into a sea of undeclared complexity that is hard for the human brain to reason about. Whereas composing pure functions leads to new pure functions &#x2013; it&apos;s pure all the way down, it&apos;s turtles all the way down.  I find it so much easier to write code when I don&apos;t have to worry about what&apos;s going on inside every function I use.</li></ul><p>That&apos;s the &apos;short list&apos;, there&apos;s probably more that I&apos;ve forgotten, but it&apos;s already pretty compelling.</p><p>The main thing to note is that if you opt-out of pure functional programming <em>anywhere </em>in an expression, then you compromise the whole expression &#x2013; it stops being turtles all the way down.  So, we want <em>everything </em>to be pure to get the compositional benefits; we need a way to encapsulate impure actions like <code>DateTime.Now</code> and, somehow, make them pure &#x2013; otherwise we may as well give up on the idea completely.</p><h3 id="back-to-the-why">Back to the &quot;why?&quot;</h3><p>OK, so pure functional programming refresher done and an unresolved issue highlighted: &apos;<em>encapsulation of impure expressions&apos;</em>.  </p><p>Let&apos;s get back to the &quot;why?&quot;.  Why do we even need monads?</p><ul><li>Monads encapsulate impure side-effects and other effects, making them pure<ul><li><em>Ding, ding!</em></li></ul></li><li>Monads allow sequencing of operations, like the <code>let</code> example earlier, so that we can chain expressions together.</li><li>Monads (with LINQ in C#) allows us to write <em>pure</em> code that looks a lot like statements in <em>imperative</em> code.</li></ul><blockquote>Quite simply: <em>Monads are the &apos;statements&apos; of pure functional programming and they encapsulate messy side-effects.</em></blockquote><p>And so, when you see people struggling to explain monads, or they&apos;re trying to bring them into a domain that isn&apos;t pure (or their goal isn&apos;t to enable a pure functional programming experience) then I think the reasoning in favour of monads goes awry.</p><p>Monads are simply a design-pattern for pure functional programmers.  That is all.  No more. </p><p>OK, that was a lot of words to say &quot;it&apos;s a design pattern&quot;, but hopefully now you have some context for why we&apos;re even doing this.  </p><blockquote>It must be stated that, beyond the justifications above, they also encapsulate some truly awesome patterns that are not served by any other technique <em>and </em>they are super-powered boilerplate killers!</blockquote><p>So, let&apos;s get back to <code>DateTime.Now</code>.  And let&apos;s try to make that pure.  What does <code>DateTime.Now</code> do?  Well, it accesses the system-clock and uses that to give you a <code>DateTime</code> struct which is a <em>snapshot</em> of the current-time.</p><p><code>DateTime.Now</code> is clearly doing an IO operation.  It is accessing some state outside of the application and then returning that state.  So, why don&apos;t we start by creating a type called <code>IO&lt;A&gt;</code>:</p><pre><code class="language-csharp">public record IO&lt;A&gt;(Func&lt;A&gt; runIO);</code></pre><p>Notice how we&apos;re capturing a <code>Func&lt;A&gt;</code> and not a value.  This is important because we&apos;re not trying to capture a <em>snapshot</em> but a <em>computation</em>.</p><p>OK, now let&apos;s create our own <code>DateTime</code> module (we&apos;ll call it <code>DateTimeIO</code> to avoid a name clash):</p><pre><code class="language-csharp">public static class DateTimeIO
{
    public static readonly IO&lt;DateTime&gt; Now =
        new (() =&gt; DateTime.Now);
}</code></pre><p>So, now, instead of returning a <code>DateTime</code> we return an <code>IO&lt;DateTime&gt;</code>.  This is the <em>&apos;get out of jail free card&apos;, </em>it means the return value isn&apos;t a snapshot of time any more.  You can replace any call to <code>DateTimeIO.Now</code> with the resulting <code>IO&lt;DateTime&gt;</code> in any expression and the result will be the same.  We&apos;ve taken something that was impure and made it pure.</p><blockquote>You might think that this is a sleight of hand, but it really isn&apos;t.  The rules hold.  We are still returning a data-structure, but it&apos;s a data representation of a computation, rather than a snapshot data-structure.  The call to <code>DateTimeIO.Now</code> is interchangeable with <code>IO&lt;DateTime&gt;</code> in a pure expression.</blockquote><p>The problem is that the code that wanted to use the <code>DateTime</code> snapshot, now can&apos;t, it has an <code>IO&lt;DateTime&gt;</code> not a <code>DateTime</code> &#x2013; so what do we do? If you remember the discussion about lifting, this is a situation where we have a <em>lifted computation</em>, so we need to work in the <em>lifted space</em>.  The first step is to make the <code>IO&lt;A&gt;</code> type into a <code>Functor</code>: </p><p>So, as with the examples in the previous articles, derive the type from <code>K&lt;F, A&gt;</code>:</p><pre><code class="language-csharp">public record IO&lt;A&gt;(Func&lt;A&gt; runIO) : K&lt;IO, A&gt;;
</code></pre><p>Add an extension to downcast:</p><pre><code class="language-csharp">public static class IOExtensions
{
    public static IO&lt;A&gt; As&lt;A&gt;(this K&lt;IO, A&gt; ma) =&gt;
        (IO&lt;A&gt;)ma;
}
</code></pre><p>Let&apos;s also have an extension that will run the <code>IO</code> computation to get a concrete value:</p><pre><code class="language-csharp">public static class IOExtensions
{
    public static IO&lt;A&gt; As&lt;A&gt;(this K&lt;IO, A&gt; ma) =&gt;
        (IO&lt;A&gt;)ma;

    public static A Run&lt;A&gt;(this K&lt;IO, A&gt; ma) =&gt;
        ma.As().runIO();
}</code></pre><p>Then we can start building the <code>IO</code> trait-implementation class:</p><pre><code class="language-csharp">public class IO : Functor&lt;IO&gt;
{
    public static K&lt;IO, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;IO, A&gt; ma) =&gt;
        new IO&lt;B&gt;(() =&gt; f(ma.Run()));
}
</code></pre><p>What we&apos;re doing in the <code>Map</code> function is invoking the <code>Func</code> inside the <code>IO&lt;A&gt;</code> type.  It returns an <code>A</code> value; we pass that value to the <code>f</code> function, which gives us a <code>B</code>; and we then wrap that all inside a new <code>Func</code> so we can construct an <code>IO&lt;B&gt;</code>. </p><p>That means we can now work with the value within the <code>IO&lt;A&gt;</code> :</p><pre><code class="language-csharp">var thisTimeTomorrow = DateTimeIO.Now.Map(now =&gt; now.AddDays(1));</code></pre><blockquote>Hopefully it&apos;s obvious that every time we use <code>DateTimeIO.Now</code> we will get the latest time.  That is also true if we assign <code>DateTimeIO.Now</code> to another variable and use that variable at some point in the future.</blockquote><p>So, as seen in previous articles, we can <em>lift</em> functions into the <code>IO</code> functor and work with the value within.  </p><p>Next, we can upgrade the <code>IO</code> type to be an <code>Applicative</code>:</p><pre><code class="language-csharp">public class IO : Applicative&lt;IO&gt;
{
    public static K&lt;IO, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;IO, A&gt; ma) =&gt;
        new IO&lt;B&gt;(() =&gt; f(ma.Run()));

    public static K&lt;IO, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new IO&lt;A&gt;(() =&gt; value);

    public static K&lt;IO, B&gt; Apply&lt;A, B&gt;(K&lt;IO, Func&lt;A, B&gt;&gt; mf, K&lt;IO, A&gt; ma) =&gt;
        mf.Map(f =&gt; f(ma.Run()));
}
</code></pre><p>Both of these steps are needed on the way to making <code>IO</code> into a monad, we&apos;ve done this in previous articles, so I&apos;m pushing through quickly...</p><p>Now, let&apos;s upgrade the <code>IO</code> type to be a <code>Monad</code>:</p><pre><code class="language-csharp">public class IO : Monad&lt;IO&gt;
{
    public static K&lt;IO, B&gt; Bind&lt;A, B&gt;(K&lt;IO, A&gt; ma, Func&lt;A, K&lt;IO, B&gt;&gt; f) =&gt;
        new IO&lt;B&gt;(() =&gt; f(ma.Run()).Run()); 

    public static K&lt;IO, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;IO, A&gt; ma) =&gt;
        new IO&lt;B&gt;(() =&gt; f(ma.Run()));

    public static K&lt;IO, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new IO&lt;A&gt;(() =&gt; value);

    public static K&lt;IO, B&gt; Apply&lt;A, B&gt;(K&lt;IO, Func&lt;A, B&gt;&gt; mf, K&lt;IO, A&gt; ma) =&gt;
        mf.Map(f =&gt; f(ma.Run()));
}
</code></pre><p>The new function is <code>Bind</code>.  If you look at the <code>f</code> function for both <code>Map</code> and <code>Bind</code>, you&apos;ll notice that the only difference is that instead of returning a <code>B</code> the <code>Bind</code> version of <code>f</code> returns an <code>IO&lt;B&gt;</code>.  </p><p>So, monad <code>Bind</code> and functor <code>Map</code> are very similar.  We can even write <code>Map</code> in terms of <code>Bind</code> and <code>Pure</code>:</p><pre><code class="language-csharp">public static K&lt;IO, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;IO, A&gt; ma) =&gt;
    Bind(ma, x =&gt; Pure(f(x)));
</code></pre><p>Which might give you a bit of insight into the similarities and differences between <code>Map</code> and <code>Bind</code>.  The similarities are mostly aesthetic &#x2013; they look similar.  However, the differences are huge: by returning a new monad instead of a concrete value, we are inviting a <em>chain</em> of operations to happen.  The implementation of <code>Map</code> (in terms of <code>Bind</code> and <code>Pure</code> above) highlights that <code>Pure</code> means &apos;terminate the chain&apos;.  <em>Stop the operation here.  </em>So, <code>Map</code> is like a <code>Bind</code> operation that always terminates.</p><p>Applicative <code>Apply</code> can also be implemented in terms of <code>Bind</code> and <code>Map</code>:</p><pre><code class="language-csharp">public static K&lt;IO, B&gt; Apply&lt;A, B&gt;(K&lt;IO, Func&lt;A, B&gt;&gt; mf, K&lt;IO, A&gt; ma) =&gt;
    mf.Bind(ma.Map);
</code></pre><p>Which is quite elegant and is nearly always a good first implementation of <code>Apply</code>, but for some monads it&apos;s better to have a bespoke <code>Apply</code> method.</p><p>Now, let&apos;s look at the internals of <code>Bind</code> a little closer:</p><pre><code class="language-csharp">f(ma.Run()).Run()</code></pre><p>We get the first <code>IO&lt;A&gt;</code> &#x2013; run it &#x2013; then invoke <code>f</code> with the result.  The result of <code>f</code> is an <code>IO&lt;B&gt;</code> which we also run.  So, that&apos;s one IO operation that runs, that returns a new IO operation, which we run too.  </p><p>Sounds like two operations:</p><pre><code class="language-csharp">doTheFirstThing();
thenDoTheNextThing();</code></pre><p><code>Bind</code> is how &apos;statements&apos; are done in pure functional programming.  </p><p>Let&apos;s add a few more <code>IO</code> values to our <code>DateTimeIO</code> type:</p><pre><code class="language-csharp">public static class DateTimeIO
{
    public static readonly IO&lt;DateTime&gt; Now =
        new (() =&gt; DateTime.Now);
    
    public static readonly IO&lt;DateTime&gt; Today =
        new (() =&gt; DateTime.Today);

    public static readonly IO&lt;DateTime&gt; Tomorrow =
        new (() =&gt; DateTime.Today.AddDays(1));
}
</code></pre><p>And now, let&apos;s try to use <code>Bind</code>:</p><pre><code class="language-csharp">var diff = DateTimeIO.Today.Bind(
    today =&gt; DateTimeIO.Tomorrow.Map(
        tomorrow =&gt; tomorrow - today));
</code></pre><p>So, <code>Bind</code> allows another <code>IO</code> operation inside its injected function.  In theory you can do this multiple times (with any number of <code>IO</code> operations).  But, as you can probably tell, that will turn into a <a href="https://en.wikipedia.org/wiki/Pyramid_of_doom_(programming)?ref=paullouth.com">pyramid-of-doom</a> quite quickly.</p><p>You can also write the above example with two nested <code>Bind</code> calls and an <code>IO.pure</code>:</p><pre><code class="language-csharp">var diff = DateTimeIO.Today.Bind(
    today =&gt; DateTimeIO.Tomorrow.Bind(
        tomorrow =&gt; IO.pure(tomorrow - today)));
</code></pre><p>Now the terminating <code>Pure</code> seems more obvious!</p><p>To deal with the pyramid-of-doom we need some first-class language support.  In Haskell, they deal with this using <code>do</code> notation, it might look something like this:</p><pre><code class="language-haskell">diff = do
  today    &lt;- DateTimeIO.today
  tomorrow &lt;- DateTimeIO.tomorrow
  pure (tomorrow - today)</code></pre><blockquote>Notice the <code>pure</code> terminator</blockquote><p>In C# our equivalent is LINQ.  It is genuine first-class monad support in C#.  The only thing we couldn&apos;t do in the past with LINQ was to generalise over <em>all</em> monads.  But, now &#x2013; with the higher-kinded types in language-ext &#x2013; we can.  Once you have implemented the <code>Monad&lt;M&gt;</code> trait for your type, it will <strong>immediately</strong> work in LINQ (no need to manually implement <code>Select</code> and <code>SelectMany</code>):</p><pre><code class="language-csharp">var diff = from today    in DateTimeIO.Today
           from tomorrow in DateTimeIO.Tomorrow
           select tomorrow - today;
</code></pre><blockquote>I often see other language ecosystems trying to bring monads into their domain.  But, without first-class support for monads (like <code>do</code> notation in Haskell or LINQ in C#), they are (in my humble opinion) too hard to use.  LINQ is the killer feature that allows C# to be one of very few languages that can facilitate genuine pure functional programming.  </blockquote><p>I just wish Microsoft would put some effort into improving LINQ:</p><ul><li>Discards for variable names (<code>from _ in foo</code>)</li><li>Allocation free local lambdas to reduce the garbage</li><li>Remove need to use <code>select</code> as the last term, allow a lifted type to be evaluated as the final term.  This will allow for recursive monads that use trampolining internally (enabling infinite recursion).</li></ul><p>So, Microsoft, please, this is your killer feature!</p><h3 id="pause">Pause</h3><p>It&apos;s worth reviewing where we are, because we now have a fully fledged IO monad (and applicative, and functor!) with just this code:</p><pre><code class="language-csharp">public record IO&lt;A&gt;(Func&lt;A&gt; runIO) : K&lt;IO, A&gt;;

public static class IOExtensions
{
    public static IO&lt;A&gt; As&lt;A&gt;(this K&lt;IO, A&gt; ma) =&gt;
        (IO&lt;A&gt;)ma;

    public static A Run&lt;A&gt;(this K&lt;IO, A&gt; ma) =&gt;
        ma.As().runIO();
}

public class IO : Monad&lt;IO&gt;
{
    public static K&lt;IO, B&gt; Bind&lt;A, B&gt;(K&lt;IO, A&gt; ma, Func&lt;A, K&lt;IO, B&gt;&gt; f) =&gt;
        new IO&lt;B&gt;(() =&gt; f(ma.Run()).Run());

    public static K&lt;IO, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;IO, A&gt; ma) =&gt;
        Bind(ma, x =&gt; Pure(f(x)));

    public static K&lt;IO, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new IO&lt;A&gt;(() =&gt; value);

    public static K&lt;IO, B&gt; Apply&lt;A, B&gt;(K&lt;IO, Func&lt;A, B&gt;&gt; mf, K&lt;IO, A&gt; ma) =&gt;
        mf.Bind(ma.Map);
}</code></pre><p>I spent a lot of time in earlier versions of language-ext building code-gen solutions to make it easy to generate monadic types.  And now, without any code-gen, we have a much more powerful system that you can build by hand.  Very cool!</p><h4 id="naming">Naming </h4><p>Some other &apos;Yet Another Monad Tutorial&apos; writers have tried to avoid using the word &apos;monad&apos;, or have introduced it at the end of the tutorial, or have renamed the concept entirely.</p><p>Personally, I believe if you&apos;re going to come along for the <em>&apos;pure functional ride&apos;</em>, then you need to know how to communicate with other people in the space; as well as be able to search online for further information on the subject.  And that mostly means understanding the lexicon of Haskell, Scala, PureScript, etc.  There&apos;s a common dialect and I think sticking with it, even if the words sometimes feel ugly, is the right way to go.</p><p>But, if it helps, here are some approachable names that might help give a more instinctive understanding:</p><ul><li><code>Chainable</code> instead of <code>Monad</code> &#x2013;  to represent the fact that operations are chained serially.</li><li><code>AndThen</code> or <code>Then</code> instead of <code>Bind</code> </li></ul><h2 id="composition">Composition</h2><p>In <a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">the article on <code>Validation</code></a> &#x2013; which was an extended discussion of Applicatives &#x2013; there is a diagram (repeated below) that has lower-kinds at the bottom, higher-kinds above and the various functions (arrows) that map between the types.</p><figure class="kg-card kg-image-card"><img src="https://paullouth.com/content/images/2024/04/Functors3-2.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 7 - monads]" loading="lazy" width="1600" height="936" srcset="https://paullouth.com/content/images/size/w600/2024/04/Functors3-2.png 600w, https://paullouth.com/content/images/size/w1000/2024/04/Functors3-2.png 1000w, https://paullouth.com/content/images/2024/04/Functors3-2.png 1600w" sizes="(min-width: 720px) 720px"></figure><ul><li>The bottom <code>toString</code> arrow is saying: &quot;If you provide an <code>int</code>, I will give you a <code>string</code> in return&quot; (basic function invocation).</li><li>The top <code>Maybe&lt;toString&gt;</code> arrow is saying &quot;If you provide a <code>Maybe&lt;int&gt;</code>, I will give you a <code>Maybe&lt;string&gt;</code> in return&quot; (applicative <code>Apply</code>)</li></ul><p>So, if you follow the arrows we have various composition options:</p><ul><li><code>int -&gt; Maybe&lt;int&gt; -&gt; Maybe&lt;string&gt;</code> which composes to <code>int -&gt; Maybe&lt;string&gt;</code></li><li><code>int -&gt; string -&gt; Maybe&lt;string&gt;</code> which also composes to <code>int -&gt; Maybe&lt;string&gt;</code></li><li><code>int -&gt; string</code></li><li><code>Maybe&lt;int&gt; -&gt; Maybe&lt;string&gt;</code></li><li><code>int -&gt; Maybe&lt;int&gt;</code></li><li><code>string -&gt; Maybe&lt;string&gt;</code></li></ul><p>These arrows and compositions give us the full set of transformations for each of the types in the diagram.  They also hint at potential optimisations: if there are two routes that start and end in the same place, which one is more efficient?</p><p>What we don&apos;t have is any way to get from:</p><ul><li><code>Maybe&lt;int&gt; -&gt; int</code> </li><li><code>Maybe&lt;string&gt; -&gt; string</code></li></ul><p>Because there are no arrows there to follow.  Do we need them? And do they make sense? </p><p>Usually, going from higher-kinds to lower-kinds is a destructive action.  For example, to make <code>Maybe&lt;int&gt;</code> (equivalent of <code>Option&lt;int&gt;</code> in language-ext) collapse down to an <code>int</code> would require us to have a <em>default value</em> to use in case the type is in a <code>Nothing</code> (<code>None</code>) state.  </p><p>These types of &apos;lowering&apos; functions are type-specific and don&apos;t have abstractions that we can discuss.  For discriminated-union types the function is usually a pattern-match operation that collapses the union down to a non-union type.  So, we&apos;ll consider that to not be an option for trait-level programming.</p><p>However, lowering <em>optionally</em> to work on the values <em>within</em> the type, to then re-lift into the higher space <em>is </em>possible.  And that is the <code>Bind</code> function...</p><p>If we look at the <code>Monad</code> trait we can get some clues:</p><pre><code class="language-csharp">public interface Monad&lt;M&gt; : Applicative&lt;M&gt; 
    where M : Monad&lt;M&gt;
{
    public static abstract K&lt;M, B&gt; Bind&lt;A, B&gt;(K&lt;M, A&gt; ma, Func&lt;A, K&lt;M, B&gt;&gt; f);

    // default implementations removed for clarity
}</code></pre><p>So, we have an argument called <code>ma</code> which is of type: <code>M&lt;A&gt;</code>.  That is a &apos;structure&apos; with zero or more <code>A</code> values within &#x2013; from the <em>outside </em>we have no idea what&apos;s <em>inside &#x2013; </em>but that doesn&apos;t matter, the implementation of the <code>Bind</code> function knows what&apos;s <em>inside</em>.  </p><p>The <code>Bind</code> implementation must extract the <code>A</code> value(s) so that it can pass them to the function <code>f</code> which in return gets us an <code>M&lt;B&gt;</code>.</p><p>Or, more concisely:</p><pre><code class="language-text">M&lt;A&gt; -&gt; A -&gt; M&lt;B&gt;</code></pre><p>So, the effect of the <code>Bind</code> action is to <em>zig-zag</em> between higher and lower kinds.  </p><figure class="kg-card kg-image-card"><img src="https://paullouth.com/content/images/2024/04/monad-arrows-1.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 7 - monads]" loading="lazy" width="1820" height="952" srcset="https://paullouth.com/content/images/size/w600/2024/04/monad-arrows-1.png 600w, https://paullouth.com/content/images/size/w1000/2024/04/monad-arrows-1.png 1000w, https://paullouth.com/content/images/size/w1600/2024/04/monad-arrows-1.png 1600w, https://paullouth.com/content/images/2024/04/monad-arrows-1.png 1820w" sizes="(min-width: 720px) 720px"></figure><p>The &apos;lowering&apos; arrows (those pointing down) are the bespoke behaviour of the monad.  If it&apos;s an <code>IO</code> monad then it knows how to run the internal <code>Func&lt;A&gt;</code> computation that extracts the <code>A</code> value.  If it&apos;s an <code>Option&lt;A&gt;</code> monad then it does a check to make sure that the structure is in a <code>Some</code> state, and if so it yields the value.</p><p>So, why can&apos;t the lowering arrow be used to create a generalised lowering function?  Because the higher-kind might not actually have <em>any</em> values within it.  <code>Option&lt;A&gt;</code> might be <code>None</code>, so we can&apos;t yield an <code>A</code>.  But, we can map <code>Option&lt;A&gt;.None</code> to <code>Option&lt;B&gt;.None</code> &#x2013; because we can pluck a <code>None</code> out of thin air.  That allows the &apos;contract&apos; of <code>Bind</code> to be honoured: <code>M&lt;A&gt; -&gt; M&lt;B&gt;</code>,</p><p>This is also the essence of the <em>short-cutting</em> behaviour of monads.  If there&apos;s no value to yield then the <code>f</code> function passed to <code>Bind</code> never gets called because we have no value to give it!  </p><p>And, because we know that monads <em>chain</em> expressions together serially; not calling <code>f</code>  means <em>the rest of the expression</em> isn&apos;t invoked either.  We essentially exit out of the computation early.</p><blockquote>There&apos;s another common phrase used to describe monads: &quot;programmable semicolons&quot;.  Although it is slightly misleading, you can see the <em>lowering-arrow</em> as the point between two computations (two statements) where additional logic lies.  This logic can do lots of different things.  In the case of <code>Option</code> it is effectively a &apos;null check&apos; to see if we even have a value &#x2013; and if not, it bails out of the computation.</blockquote><p>Let&apos;s take a look at two examples using <code>Option</code> from language-ext:</p><pre><code class="language-csharp">var inp1 = &quot;100&quot;;
var inp2 = &quot;200&quot;;
var inpX = &quot;NUL&quot;;

var res1 = from x in parseInt(inp1)
           from y in parseInt(inp2)
           select x + y;

var res2 = from x in parseInt(inp1)
           from y in parseInt(inpX) // fails to parse, `y` is never assigned
           from z in parseInt(inp2) // never executes
           select x + y + z;        // never executes

// res1 == Some(300)
// res2 == None</code></pre><p>The <code>parseInt</code> function returns an <code>Option&lt;int&gt;</code> and it will be <code>None</code> if the parse fails.  </p><p>On the first example, everything parses correctly, which means the final <code>x + y</code> is run.</p><p>On the second example, the <code>parseInt(inpX)</code> will return <code>None</code> which means the we have no value to assign to <code>y</code>.  And therefore we must exit, because the rest of the expression depends on <code>y</code> having a valid value.</p><p>If we look at the implementation of <code>Bind</code> for <code>Option</code> we can see this short-cutting behaviour:</p><pre><code class="language-csharp">static K&lt;Option, B&gt; Bind&lt;A, B&gt;(K&lt;Option, A&gt; ma, Func&lt;A, K&lt;Option, B&gt;&gt; f) =&gt;
    ma.Match(
        Some: x =&gt; f(x),
        None: Option&lt;B&gt;.None);
</code></pre><p>We pattern-match on the <code>Option</code>, if we&apos;re in a <code>Some</code> state then we call the <code>f</code> function that continues the expression.  If we&apos;re in a <code>None</code> state, we just return <code>None</code> &#x2013; halting the expression.</p><p>It&apos;s remarkably simple really, but extremely effective because this won&apos;t allow you to continue unless we have a value.  It can&apos;t be cheated.  You can&apos;t make a mistake when using <code>Option</code> &#x2013; whereas similar <code>if</code> checks for <code>null</code> values (or the accidental absence of them) can lead to major bugs.</p><p>Another interesting aspect of <code>Option&lt;A&gt;</code> is that it helps us fulfil our <em>pure functional programming mandate</em>.  Remember, we shouldn&apos;t have any side-effects in our functions or expressions.  Exceptions are side-effects.  Really, if method-signatures in C# were honest, we&apos;d never have a return type of <code>void</code>.  And methods that throw exceptions might look something like this:</p><pre><code class="language-csharp">(Exception | int) ParseInt(string value)</code></pre><p>Exceptions should be for truly <em>exceptional</em> events that you can&apos;t recover from.  <em>Exceptions should not be thrown for <strong>expected</strong> errors &#x2013; a failure to parse is expected for a parsing function</em>.  </p><p>I saw an <a href="https://twitter.com/terrajobst/status/1782990040358076613?ref=paullouth.com">interesting post</a> the other day on Twitter, from a PM on the .NET team at Microsoft, he was lamenting the incorrect usage of <code>ArgumentException</code> &#x2013; and then giving advice on what should be done.  Completely oblivious to the fact that exceptions are just the wrong approach.  The system clearly isn&apos;t working as intended; and that&apos;s because there&apos;s no compiler support, there&apos;s no type-system support, it&apos;s just convention.</p><p>I find it crazy that something like that even needs to be written.  The correct approach is to make your function <em>total</em> &#x2013; that means for every combination of values provided to the function as arguments there should be an associated value in your return type: every value in your <em>domain</em> should <em>map</em> to a value in your <em>co-domain</em>. This honours the requirement for the output of a pure function being totally dependent on its inputs.</p><p>How do we do this?</p><ul><li>Constrain the types that are used for the arguments.  Make sure there&apos;s no possibility of constructing input values that are &apos;out of range&apos;. </li><li>Where the input arguments are constrained as much as possible, but the combined states of <em>all</em> arguments still falls outside of what the <em>co-domain</em> can handle, augment the co-domain with a failure value.  This is where <code>Option&lt;A&gt;</code> comes in.  It allows us to return <code>None</code> if we&apos;re unable to handle the input values: <em>we augment the co-domain</em>.</li></ul><p>This leads to declarative type signatures like below.  Type signatures that <em>speak</em> to programmers:</p><pre><code class="language-csharp">Option&lt;int&gt; parseInt(string value)</code></pre><p>Monads are a <strong>big</strong> part of the declarative programming story.  They &apos;mark&apos; whole sections of code as having a particular <em>flavour.</em>  For example, once you&apos;re working in the IO monad you have <em>declared </em>that code as something that &apos;<em>does IO&apos;</em>.  I know that might sound obvious, but it encourages you to separate your non-IO code from your IO code, which leads to more composition options, and ultimately more robust code.</p><blockquote>By the way, this is why you shouldn&apos;t ever really call <code>.Run()</code> on the IO monad (well, not externally, internal behaviours like <code>Map</code> and <code>Bind</code> are fine).  Once you&apos;re in an IO lifted space you should stay there to indicate the expression &apos;does IO&apos;.  The place to call <code>Run</code> is <strong>once</strong> in your <code>Main</code> function.  Although, because we sometimes need more flexibility in C#, once in your web-request handler also makes sense.  Collapsing <code>IO&lt;A&gt;</code> down to <code>A</code> re-injects  your code with impure effects, breaking the pure functional programming mandate.</blockquote><p>So far we&apos;ve seen that:</p><ul><li>The <code>Bind</code> function for the <code>IO&lt;A&gt;</code> monad allows us to make <em>impure</em> operations, <em>pure</em>.  </li><li>The <code>Bind</code> function for the <code>Option&lt;A&gt;</code> monad allows us to deal with functions that might not be able to return a value (<a href="https://en.wikipedia.org/wiki/Partial_function?ref=paullouth.com">partial function</a>) and, if no value is available,  the <code>Bind</code> function automatically short-cuts the expression to stop accidental usage of <code>None</code> values.</li></ul><p>The behaviour of the two <code>Bind</code> functions are dramatically different to each other, yet they share the same abstraction: they&apos;re both monads.  </p><p>It turns out there are many different <em>&apos;flavours&apos; </em>of <code>Bind</code> function that can be written that cover a whole slew of behaviours; from resource-tracking, state-management, configuration, logging, validation, list iteration, stream-processing, etc. etc.  They&apos;re all just different implementations of <code>Bind</code>.  I think this is another reason why Yet Another Monad Tutorials are quite hard to write: there&apos;s so much that you <em>can </em>do.  </p><p>If you can program your semicolons, where&apos;s the limit!? How could you possibly write a tutorial that covers it all?</p><p>Ultimately, the <code>Bind</code> function is just another form of function composition.  The result of the composition is: <code>M&lt;A&gt; -&gt; M&lt;B&gt;</code>.  Where <code>M</code> is the <em>flavour </em>of monad.</p><blockquote>Everything in functional programming is function composition. E v e r y t h i n g.  Monads are just another flavour of function composition that works with slightly different arrows to the other flavours!  I know the abstractions are sometimes a bit hard to picture, but often it just means lining up the types and following the arrows.  In many ways it ends up being more like Lego than programming!</blockquote><p>This article is now probably one of the longest so far (with the fewest code examples); I realise there were a number of diversions into &apos;<em>the why&apos;</em> of pure functional programming, but I feel that is the real <em>origin-story</em> of monads and why you should care about them.  </p><p>That has made this article a bit longer and wordier, but hopefully it sets the scene nicely for the next episode.  In the next article we&apos;ll dig into the different types of monad in language-ext and also discuss monad &apos;join&apos;, also known as <code>Flatten</code>.</p><p><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-8-monads-continued/"><em><strong>Part 8:</strong> Monads continued</em></a><em> </em></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 6 - traversables]]]></title><description><![CDATA[Traversables leverage the power of applicatives and foldables to allow for complex processing over those abstract strucutures...]]></description><link>https://paullouth.com/higher-kinds-in-csharp-part6-traversables/</link><guid isPermaLink="false">65eeaa372ac0342e8bc9364f</guid><category><![CDATA[traversable]]></category><category><![CDATA[traits]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[hkt]]></category><category><![CDATA[functor]]></category><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Tue, 16 Apr 2024 10:30:47 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/04/traversable.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/04/traversable.png" alt="Higher Kinds in C# with language-ext [Part 6 - traversables]"><p>This is a multi-part series of articles, it&apos;s worth going back to the earlier parts if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/">Part 5 - Validation</a> </li></ul><p>One interesting stat is that I have managed to remove nearly half a million lines of code from the <code>v5</code> release of <a href="https://github.com/louthy/language-ext?ref=paullouth.com">language-ext</a>.  At least 200,000 of those lines were auto-generated by some T4 templates (<code>LanguageExt.Transfomers</code>, which has now been deleted entirely); the rest of the deletions were from hand-written types and extension methods used to simulate higher-kinds (<code>OptionAsync&lt;A&gt;</code> for example, is emulating the (new) monad-transformer stack <code>OptionT&lt;IO, A&gt;</code>).  </p><p>The reason that so many lines of code have been removed is because we don&apos;t need to emulate higher-kinds any more, we really can write: <code>OptionT&lt;IO, A&gt;</code>, whereas before we relied on generated extension methods (I&apos;ll talk about transformers in a later article).  </p><p>So, if the removal of nearly half a million lines of code doesn&apos;t justify the techniques I am highlighting in this series, I really don&apos;t know what will!  Less code pretty much always means fewer bugs and easier long-term maintenance &#x2013; something I am particularly looking forward to once this release is stable!  </p><blockquote>Also, <code>v5</code> has much more functionality &#x2013; not less!</blockquote><p>One thing I noticed as I was working through all of the original language-ext unit-tests &#x2013;  trying to turn them all green &#x2013;  was that I discovered some tests-cases where both the code <em>and</em> the unit-test had a bug.  The bugs discovered were in the manually written <code>Traverse</code> and <code>Sequence</code> functions.  </p><p>On [some of the implementations of <code>Traverse</code>] I had made wrong assumptions <em>and </em>I had carried those wrong assumptions through to the unit-tests!  It doesn&apos;t matter how good you are at programming, you will always end up making stupid mistakes like this &#x2013; which is why I much prefer to leverage types over unit-tests: you can&apos;t cheat the compiler, but you can easily cheat yourself!</p><p>The new implementations of <code>Traverse</code> (leveraging the higher-kinded traits) exposed those bugs &#x2013; because they are now following the rules of the trait-types &#x2013; not the assumptions of a human that errs.  </p><p>In the <a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Foldables article</a> I showed the graph from the <a href="https://wiki.haskell.org/Typeclassopedia?ref=paullouth.com">Haskell Typeclassopedia</a> &#x2013; we&apos;re quite a way into implementing the key traits from this diagram:  </p><figure class="kg-card kg-image-card"><img src="https://paullouth.com/content/images/2024/04/Typeclassopedia-diagram.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 6 - traversables]" loading="lazy" width="753" height="260" srcset="https://paullouth.com/content/images/size/w600/2024/04/Typeclassopedia-diagram.png 600w, https://paullouth.com/content/images/2024/04/Typeclassopedia-diagram.png 753w" sizes="(min-width: 720px) 720px"></figure><p>In this article we will take on the Traversable trait.  You can see from the diagram above that there are three arrows leading into the Traversable trait: Functor, Foldable, and Applicative.  We have already implemented these in previous articles, so we have all of the components needed to create a <code>Traversable</code> trait.</p><p>But what are traversables?  Simply, traversables are a little bit like foldables in that you can iterate over many items in a structure, aggregating as you go.  Except, traversables don&apos;t expose an aggregated state-value, they instead return a nested foldable/applicative structure.  The aggregation comes from running the default applicative behaviour for the structure instead of a provided fold function.  This nested structure is &apos;<em>flipped&apos;</em> so what was inner becomes outer and what was outer becomes inner.  </p><p>That explanation is too abstract, so let&apos;s take a look at an example.  Below, we have a collection of strings that we want to parse into integers.  Not all strings can be parsed into a valid integer, so we need a way to deal with the failure to parse:</p><pre><code class="language-csharp">var items = Seq(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;);
var values = items.Map(s =&gt; parseInt(s));</code></pre><p>The example above takes a <code>Seq&lt;string&gt;</code>, each value is passed to the <code>parseInt</code> function from the language-ext <code>Prelude</code>.  <code>parseInt</code> returns an <code>Option&lt;int&gt;</code>.  And so, the result of this would be:</p><pre><code class="language-text">[Some(1), Some(2), Some(3), Some(4), Some(5)]</code></pre><p>So, the success of the parsing is embedded into the list.  </p><p>If we had an item that caused a failure:</p><pre><code class="language-csharp">var items = Seq(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;X&quot;, &quot;5&quot;);  // NOTE: 4th item is &apos;X&apos;
var values = items2.Map(s =&gt; parseInt(s));
</code></pre><p>Then the result looks like this:</p><pre><code class="language-text">[Some(1), Some(2), Some(3), None, Some(5)]</code></pre><p>Now we can tell which items succeed and which failed.  Which on its own is pretty useful, but if we want to work with the values in the list we have to do work on every step to test that the value exists. </p><p>Often, we want to know whether <em>all</em> items succeeded and only proceed if that is the case.  And we often want to early out if any fail, not to continue to parse the rest of the list.</p><p>This is where <code>Traverse</code> comes in.  Simply replace <code>Map</code> with <code>Traverse</code>:</p><pre><code class="language-csharp">var items = Seq(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;);
var values = items.Traverse(s =&gt; parseInt(s));</code></pre><p>Now the output is this:</p><pre><code class="language-text">Some([1, 2, 3, 4, 5])</code></pre><p>We have &apos;flipped&apos; the type.  Instead of a <code>Seq&lt;Option&lt;int&gt;&gt;</code> we now have an <code>Option&lt;Seq&lt;int&gt;&gt;</code> &#x2013; <em>this is the magic of traverse</em>.  It follows the rules of the outer applicative (<code>Option</code>) to accumulate the inner foldable (<code>Seq</code>) &#x2013; resulting in the behaviour of <code>Option</code> being embedded for each item in the sequence.  </p><p>If we have a collection where the transformation would produce <code>None</code> ...</p><pre><code class="language-csharp">var items = Seq(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;X&quot;, &quot;5&quot;);
var values = items.Traverse(s =&gt; parseInt(s));
</code></pre><p>... then we get:</p><pre><code class="language-text">None    // Option&lt;Seq&lt;int&gt;&gt;</code></pre><p>If any item fails, they all fail.</p><p>This works for <em>all</em> foldables with <em>all </em>applicatives &#x2013; injecting the default applicative behaviour for each step (which, by the way, may not shortcut the operation, as it does with <code>Option</code>). </p><p>Here&apos;s a simple example using the generic IO library with the <code>Eff</code> monad:</p><pre><code class="language-csharp">var items = Seq(&quot;c:\\test1.txt&quot;, &quot;c:\\test2.txt&quot;, &quot;c:\\test3.txt&quot;);
var values = items.Traverse(File&lt;Runtime&gt;.readAllText);
</code></pre><p>That will read all of the files (in parallel).  If any fail then the whole thing fails.</p><p>Applicatives such as the <code>Validation</code> type from the last article would collect all of the errors during a <code>Traverse</code> call.  And so, it should be clear that there&apos;s a lot of power lurking inside these combined types.</p><blockquote>It can&apos;t be understated how valuable <code>Traverse</code> is for pure functional programming.  It is one of the most powerful tools to reach for when you find your types are &apos;the wrong way around&apos; &#x2013; that is: the flipping of the types and the injecting of the default applicative behaviour allows for some incredibly concise transformations.  As you can see it works especially well with sequences of values &#x2013; but it&apos;s not only for sequences!</blockquote><p>Let&apos;s look at the trait definition:</p><pre><code class="language-csharp">public interface Traversable&lt;T&gt; : Functor&lt;T&gt;, Foldable&lt;T&gt; 
    where T : Traversable&lt;T&gt;, Functor&lt;T&gt;, Foldable&lt;T&gt;
{
    public static abstract K&lt;F, K&lt;T, B&gt;&gt; Traverse&lt;F, A, B&gt;(
        Func&lt;A, K&lt;F, B&gt;&gt; f,
        K&lt;T, A&gt; ta)
        where F : Applicative&lt;F&gt;;

    // ... default implementations removed for clarity ...
}
</code></pre><p>This is enough to hurt anybody&apos;s head!  I remember when I was first learning Haskell and I saw the type-signature for <code>traverse</code> &#x2013; it took me quite some time to really grok it.  Primarily because I had never really dealt with multiple levels of higher-kinded types before, so it messed with my brain a bit.  </p><p>Here&apos;s the Haskell definition:</p><pre><code class="language-haskell">class (Functor t, Foldable t) =&gt; Traversable t where
    traverse :: Applicative f =&gt; (a -&gt; f b) -&gt; t a -&gt; f (t b)

    -- default implementations removed for clarity ...</code></pre><p>You should be able to see that we have the same constraints on the <code>class</code>/<code>interface</code> as well as the same constraint on the <code>traverse</code> / <code>Traverse</code> function:</p><ul><li><code>(Functor t, Foldable t)</code> is the same as <code>: Functor&lt;T&gt;, Foldable&lt;T&gt;</code></li><li><code>Applicative f =&gt;</code> is the same as <code>where F : Applicative&lt;F&gt;</code></li></ul><p>The <code>traverse</code> / <code>Traverse</code> function also has the same arguments and return type:</p><ul><li><code>(a -&gt; f b)</code> is the same as <code>Func&lt;A, K&lt;F, B&gt;&gt;</code></li><li><code>t a</code> is the same as <code>K&lt;T, A&gt;</code></li><li><code>f (t b)</code> is the same as <code>K&lt;F, K&lt;T, B&gt;&gt;</code> </li></ul><p>The return type &#x2013;  <code>f (t b)</code> &#x2013; was what confused me when I was learning Haskell.  It should be a little clearer to you seeing the C# version: it&apos;s two, <em>nested</em>, higher-kinded types.  </p><blockquote>We have two higher-kinds: <code>F</code> and <code>T</code>.  <code>F</code> is constrained to be an applicative-functor and <code>T</code> is constrained to be a functor and a foldable.</blockquote><p>So, we pass in a value that can be folded over and mapped.  We also pass in a function that takes the bound-value of the foldable/mappable; it returns the applicative <code>K&lt;F, B&gt;</code>.</p><p>So, it should be fairly obvious that we somehow iterate over each value in the foldable/mappable <code>ta</code>, pass each value to the function <code>f</code>, and get a value back for each item.  What isn&apos;t clear is how that <code>K&lt;F, B&gt;</code> turns into a <code>K&lt;F, K&lt;T, B&gt;&gt;</code>. </p><p>As we&apos;re calling <code>Traverse</code> on <code>Seq&lt;string&gt;</code> above, let&apos;s first look at the implementation of <code>Traverse</code> for the <code>Seq</code> type:</p><pre><code class="language-csharp">static K&lt;F, K&lt;Seq, B&gt;&gt; Traverse&lt;F, A, B&gt;(Func&lt;A, K&lt;F, B&gt;&gt; f, K&lt;Seq, A&gt; ta) 
{
    return F.Map&lt;Seq&lt;B&gt;, K&lt;Seq, B&gt;&gt;(
        ks =&gt; ks, 
        Foldable.foldBack(cons, F.Pure(empty&lt;B&gt;()), ta));

    K&lt;F, Seq&lt;B&gt;&gt; cons(K&lt;F, Seq&lt;B&gt;&gt; xs, A x) =&gt;
        Applicative.lift(Prelude.Cons, f(x), xs);
}</code></pre><p>Ok, that&apos;s also enough to hurt anybody&apos;s head!  Let&apos;s break it down:</p><p>We have two arguments:</p><ul><li><code>Func&lt;A, K&lt;F, B&gt;&gt; f</code> &#x2013; this is the function that does the transformation to the applicative</li><li><code>K&lt;Seq, A&gt; ta</code> &#x2013; this is the <code>Seq&lt;A&gt;</code> that is being traversed</li></ul><p>Now let&apos;s look at the elements of the first expression. The critical part is:</p><pre><code class="language-csharp">Foldable.foldBack(cons, F.Pure(empty&lt;B&gt;()), ta)</code></pre><p>This leverages the fact that the input type (<code>ta</code>) is foldable.  The fold operation needs an initial state:</p><pre><code class="language-csharp">F.Pure(empty&lt;B&gt;())</code></pre><p><code>F</code> is the output <code>Applicative</code> - so we&apos;re <em>lifting </em><code>empty&lt;B&gt;()</code> into the <code>F</code> applicative.  <code>empty&lt;B&gt;</code> is just the constructor of an empty <code>Seq&lt;B&gt;</code>.  So, <code>F.Pure(empty&lt;B&gt;())</code> is a <code>K&lt;F, Seq&lt;B&gt;&gt;</code>.  It should be fairly clear that this is the result type before we&apos;ve processed any of the values (and indeed if the input <code>Seq&lt;A&gt;</code> is empty then this will be the result).</p><p>The function that does the folding is <code>cons</code>.  Which is a local function below the expression:</p><pre><code class="language-csharp">K&lt;F, Seq&lt;B&gt;&gt; cons(K&lt;F, Seq&lt;B&gt;&gt; xs, A x) =&gt;
    Applicative.lift(Prelude.Cons, f(x), xs);</code></pre><p>It takes in two arguments (as all fold functions do) &#x2013; the first being the running state and the second being the next item to process.  We then do an <code>Applicative.lift</code> with the <code>Cons</code> function from the <code>Prelude</code> (which prepends an item to be the new head of a list); the mapped item (<code>f(x)</code>); and the list so far <code>xs</code>.</p><blockquote><code>Applictive.lift</code> is like calling <code>fun(Prelude.Cons).Map(f(x)).Apply(xs)</code> &#x2013; it&apos;s a handy shortcut that makes it a little easier to lift functions.  </blockquote><p>And so, you should see that the applicative <code>Apply</code> method is chained for each item in the sequence.  The function being applied is the <code>Seq</code> cons function that prepends the mapped values to the head of the list.  But, if you remember (from the previous Applicative article) the <code>Apply</code> function has inbuilt behaviour depending on the structure being applied.  </p><p>And so, if we were processing a sequence of <code>Option</code> values then it would know to quit if the result of <code>f(x)</code> is <code>None</code>; if we were processing a sequence of <code>Validation</code> values it would know to collect all of the failed values; if we were processing a sequence of <code>Eff</code> effects it would know to run them in parallel; etc.</p><p>This is super, super powerful and turns into incredibly concise code.</p><p>But, there&apos;s still some code from the <code>Seq</code> implementation of <code>Traverse</code> that we haven&apos;t covered:</p><pre><code class="language-csharp">return F.Map&lt;Seq&lt;B&gt;, K&lt;Seq, B&gt;&gt;(
    ks =&gt; ks, 
    Foldable.foldBack(cons, F.Pure(empty&lt;B&gt;()), ta));</code></pre><p>The result of the <code>foldBack</code> call is mapped using <code>Functor.Map</code> &#x2013; remember the <code>F</code> is an <code>Applicative</code>, which inherits <code>Functor</code>.  We do this to convert from <code>Seq&lt;B&gt;</code> to <code>K&lt;Seq, B&gt;</code>.  So, even though <code>Seq&lt;B&gt;</code> inherits <code>K&lt;Seq, B&gt;</code> we still can&apos;t just cast the nested <code>K&lt;F, Seq&lt;B&gt;&gt;</code> to <code>K&lt;F, K&lt;Seq, B&gt;&gt;</code> because C# just does not play nice with covariant and contra-variant casting of nested types &#x2013; there were some combinations of <code>in</code> and <code>out</code> on the trait types I could use to make the above compile (without needing to <code>Map</code>) but they were causing runtime casting exceptions &#x2013; so I decided to err on the side of caution and make the casting explicit.  This adds some overhead, but is correct, which is more important.  So, we need to run a map operation to get to the base interface from the concrete nested inner-type.</p><p>Here&apos;s an alternative approach that doesn&apos;t need the <code>Map</code>:</p><pre><code class="language-csharp">static K&lt;F, K&lt;Seq, B&gt;&gt; Traversable&lt;Seq&gt;.Traverse&lt;F, A, B&gt;(Func&lt;A, K&lt;F, B&gt;&gt; f, K&lt;Seq, A&gt; ta) 
{
    return Foldable.foldBack(cons, F.Pure(empty&lt;B&gt;().Kind()), ta);

    K&lt;F, K&lt;Seq, B&gt;&gt; cons(K&lt;F, K&lt;Seq, B&gt;&gt; xs, A x) =&gt;
        Applicative.lift((b, bs) =&gt; b.Cons(bs.As()).Kind(), f(x), xs);
}
</code></pre><p>This keeps working with the abstract types all the way through the fold operation.  A few things to notice compared to the original implementation:</p><ul><li><code>empty&lt;B&gt;()</code> has <code>.Kind()</code> called on it, that turns <code>Seq&lt;B&gt;</code> into <code>K&lt;Seq, B&gt;</code></li><li>The updated <code>cons</code> function now has to convert <code>bs</code> to a <code>Seq&lt;B&gt;</code> (using <code>.As()</code>) for each item &#x2013; this is converting an interface to a struct (<code>Seq&lt;A&gt;</code> is a value-type).</li><li>Once the <code>Cons</code> operation is complete it has to be converted back to the base-interface using <code>Kind()</code></li></ul><p>Ultimately, this has to do multiple boxing operations per item (<code>.As()</code> and <code>.Kind()</code>) which adds more overhead than necessary.  And that is why this <em>isn&apos;t </em>the default implementation.</p><blockquote>It is nearly always the case that when you&apos;re traversing a collection-type, like <code>Seq&lt;A&gt;</code>, the applicative type you&apos;re mapping to is usually not a collection-type.  So, doing the <code>Map</code> operation once (for the outer <code>Applicative</code>) is much more efficient than doing it on every item.</blockquote><p>Because collections are a little more involved I wanted to present them first.  Now let&apos;s look at a simpler example: <code>Either&lt;L, R&gt;</code>:</p><pre><code class="language-csharp">// Either Traverse
static K&lt;F, K&lt;Either&lt;L&gt;, B&gt;&gt; Traverse&lt;F, A, B&gt;(Func&lt;A, K&lt;F, B&gt;&gt; f, K&lt;Either&lt;L&gt;, A&gt; ta) =&gt;
    ta switch
    {
        Either.Right&lt;L, A&gt; (var r) =&gt; F.Map(Right, f(r)),
        Either.Left&lt;L, A&gt; (var l)  =&gt; F.Pure(Left&lt;B&gt;(l)),
        _                          =&gt; throw new NotSupportedException()
    };

// Helper method to construct `Right` and cast to the underlying K type
static K&lt;Either&lt;L&gt;, A&gt; Right&lt;A&gt;(A value) =&gt;
    Either&lt;L, A&gt;.Right(value);

// Helper method to construct `Left` and cast to the underlying K type
static K&lt;Either&lt;L&gt;, A&gt; Left&lt;A&gt;(L value) =&gt;
    Either&lt;L, A&gt;.Left(value);</code></pre><p>Other than the constructor functions (<code>Left</code> and <code>Right</code>) this is much simpler and should be easier to follow.  </p><p>We simply pattern-match on <code>ta</code> which is a <code>K&lt;Either&lt;L&gt;, A&gt;</code> to find out what state the <code>Either&lt;L, A&gt;</code> is in:</p><ul><li>For the <code>Either.Right</code> case we invoke the <code>f</code> transformation function to get a resulting <code>F</code> applicative &#x2013; we then <code>Map</code> the value within the <code>Applicative</code> and lift it into the <code>Right</code> constructor, leaving us with <code>K&lt;F, K&lt;Either&lt;L, B&gt;&gt;&gt;</code>.  </li><li>For the <code>Either.Left</code> case we want to shortcut the expression, so we don&apos;t call the <code>f</code> transformation function at all and instead lift the <code>Left</code> state into the applicative using <code>F.Pure</code>.  </li></ul><p>This then captures the <code>Either</code> short-cutting effect in the <code>Traverse</code> operation &#x2013; we literally don&apos;t call the transformation operation at all if we&apos;re not in any state to deal with its result.</p><h3 id="sequence">Sequence</h3><p>In the previous version of language-ext there were also <code>Sequence</code> extension methods (for all of the types that supported <code>Traverse</code>.  <code>Sequence</code> is like calling <code>Traverse</code> with the identity function on an <em>already</em> nested pair of types:</p><pre><code class="language-csharp">var xs = Seq(Some(1), Some(2), None);  // Nested structure
var ys = xs.Sequence();                // This line is equivalent
var zs = xs.Traverse(x =&gt; x);          // to this line.

// ys == zs</code></pre><p>In <code>v5</code> of language-ext there are three additional methods with default implementations in the <code>Traversable</code> trait, including <code>Sequence</code>:</p><pre><code class="language-csharp">public static virtual K&lt;F, K&lt;T, A&gt;&gt; Sequence&lt;F, A&gt;(
    K&lt;T, K&lt;F, A&gt;&gt; ta)
    where F : Applicative&lt;F&gt; =&gt;
    Traversable.traverse(x =&gt; x, ta);

public static virtual K&lt;M, K&lt;T, B&gt;&gt; TraverseM&lt;M, A, B&gt;(
    Func&lt;A, K&lt;M, B&gt;&gt; f,
    K&lt;T, A&gt; ta)
    where M : Monad&lt;M&gt; =&gt;
    Traversable.traverse(f, ta);

public static virtual K&lt;F, K&lt;T, A&gt;&gt; SequenceM&lt;F, A&gt;(
    K&lt;T, K&lt;F, A&gt;&gt; ta)
    where F : Monad&lt;F&gt; =&gt;
    Traversable.traverseM(x =&gt; x, ta);</code></pre><p><code>Sequence</code> and <code>SequenceM</code> are functionally equal, just one constrains to <code>Applicactive</code> and the other constrains to <code>Monad</code>.  <code>TraverseM</code> is the monad equivalent of <code>Traverse</code>.  </p><p>Mostly, you&apos;d never need to implement these yourself, but there may be some traversable types that could benefit from having bespoke overridden implementations.  Specifically, collection types like <code>Seq&lt;A&gt;</code> have <code>TraverseM</code> implemented because it enforces sequential operations &#x2013; this is useful when the applicative type you&apos;re working with is asynchronous: <code>TraverseM</code> enforces a serial evaluation rather than the parallel applicative behaviour &#x2013; this enables the same functionality as <code>TraverseSerial</code> and <code>TraverseParallel</code> from <code>v4</code> &#x2013; but generalises it.</p><blockquote>BIG NOTE: <code>Sequence</code> and <code>SequenceM</code> both take <strong><em>already nested</em></strong> types.  C# doesn&apos;t like this for anything other than the nested <code>K</code> interface types, so <code>Seq&lt;Option&lt;int&gt;&gt;</code> can&apos;t be used with <code>Sequence</code> (compile-time error) &#x2013; only <code>K&lt;Seq, K&lt;Option, int&gt;&gt;</code>; so if you&apos;re already in the more abstract space then <code>Seqeunce</code> will work, otherwise not.  The workaround is to use <code>Traverse</code> with an identity function: <code>xs.Traverse(x =&gt; x)</code> &#x2013; which works fine.  This issue seems to just be a fundamental limitation of C# &#x2013; it&apos;s extremely annoying, but at least there&apos;s a workaround.</blockquote><h3 id="converting-back-to-concrete">Converting back to concrete</h3><p>The result of the <code>Traverse</code> extension method (below) is two nested <code>K</code> types.  Getting back to a concrete type isn&apos;t easy, because we can&apos;t just cast (as we do inside the <code>.As()</code> extension).</p><pre><code class="language-csharp">public static partial class TraversableExtensions
{
    public static K&lt;F, K&lt;T, B&gt;&gt; Traverse&lt;T, F, A, B&gt;(
        this K&lt;T, A&gt; ta,
        Func&lt;A, K&lt;F, B&gt;&gt; f)
        where T : Traversable&lt;T&gt;
        where F : Applicative&lt;F&gt; =&gt;
        Traversable.traverse(f, ta);
        
   ...
}</code></pre><p>Everything that works with the <code>K</code> type will continue to work: so using <code>Map</code>, <code>Apply</code>, etc. will <em>&apos;just work&apos;.  </em>But, obviously we want to get back to our concrete data types to use them...  </p><p>To make this as painless as possible, I have found that adding a <code>Traverse</code> and <code>TraverseM</code> method to your data-type reduces the complexity of getting back to a concrete state (this is in addition to the trait-implementation of <code>Traverse</code>):</p><p>Here&apos;s the <code>Traverse</code> and <code>TraverseM</code> implementation for <code>Seq&lt;A&gt;</code>:</p><pre><code class="language-csharp">public readonly struct Seq&lt;A&gt;
{
    ...
    
    public K&lt;F, Seq&lt;B&gt;&gt; Traverse&lt;F, B&gt;(Func&lt;A, K&lt;F, B&gt;&gt; f) 
        where F : Applicative&lt;F&gt; =&gt;
        F.Map(x =&gt; x.As(), Traversable.traverse(f, this));

    public K&lt;M, Seq&lt;B&gt;&gt; TraverseM&lt;M, B&gt;(Func&lt;A, K&lt;M, B&gt;&gt; f) 
        where M : Monad&lt;M&gt; =&gt;
        M.Map(x =&gt; x.As(), Traversable.traverseM(f, this));

    ...  
}</code></pre><blockquote>This implementation is pretty much always exactly the same for all types, you just need to replace <code>Seq&lt;B&gt;</code> with whatever type you&apos;re implementing.  So, copy-n-paste is your friend here.</blockquote><p>What this does is map the inner-type to its concrete-type by calling <code>.As()</code> on it.  And because this is a member of the <code>Seq&lt;A&gt;</code> type (not an extension method) it gets picked first by C# (ahead of the <code>Traverse</code> and <code>TraverseM</code> extension methods).  </p><p>It still means we have a generic outer-type (<code>K&lt;F, ...&gt;</code>), but the inner-type (<code>Seq&lt;B&gt;</code>) is now concrete.  This is then enough for us to call <code>.As()</code> on to make the whole type concrete:</p><pre><code class="language-csharp">var items = Seq(&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;X&quot;, &quot;5&quot;);
Option&lt;Seq&lt;int&gt;&gt; values = items.Traverse(s =&gt; parseInt(s)).As();</code></pre><p>This is a little bit of a rough edge for traversables.  It&apos;s a bit more effort than the other trait types and less elegant in implementation.  However, it does work without any cheating and it does turn into a truly generic system of traversables. </p><h3 id="breaking-changes-from-v4">Breaking Changes from v4</h3><ul><li>The 500 or so extension methods that existed before for <code>Sequence</code> and <code>Traverse</code> are now gone.   The methods in the trait implementations have taken over that role.  The type signatures are slightly different, with one variant of <code>Sequence</code> removed.</li><li>You nearly always want to use <code>Traverse</code> and not <code>Sequence</code> &#x2013; because C#&apos;s type-system won&apos;t play nice with your nested types most of the time.  <code>Sequence</code> is useful when the <em><strong>inner nested type</strong> is already in <code>K&lt;F, A&gt;</code> form</em>.</li><li>In pre-<code>v5</code> language-ext there were <code>Traverse</code> extension-methods for types that can&apos;t now be supported [with the new <em>fixed</em> trait-interface].  And so, you may get some breaking changes where <code>Traverse</code> doesn&apos;t exist any more for a nested-pair of types.  In reality this is unlikely, because they didn&apos;t really make much sense and were just there for completeness.</li><li><code>TraverseSerial</code> and <code>TraverseParallel</code> are currently deprecated.  The parallelisation of the operations are now dependent on the implementation of <code>Traverse</code> only.  However, types like <code>Seq&lt;A&gt;</code> also have a <code>TraverseM</code> implementation which enforces serial operations &#x2013; so you can think of <code>Traverse</code> as parallel and <code>TraverseM</code> as serial.</li><li>Because <code>Traverse</code> and <code>Sequence</code> return nested generic-types, it&apos;s not possible to make them concrete without having the same number of extension methods as before &#x2013; so you&apos;ll need to call <code>.As()</code> to get back to your concrete type (see previous section).</li></ul><h3 id="conclusion">Conclusion</h3><p>There&apos;s no doubt that there&apos;s a couple of rough edges with traversables due to the limitations of the C# type-system.  I will keep experimenting with ideas that could help improve that situation &#x2013; but I won&apos;t do any hacks, I want this to use the type-system as it is.  </p><p>Really, it would be nice to get some parity with the extension methods from <code>v4</code>, namely no issues with nested types and implicit variance casting.  Luckily, everything is still totally usable, but the issues around <code>Sequence</code> are a little frustrating.</p><p>Even with all of that said, this version now has the bugs in <code>Traverse</code> and <code>Sequence</code> &#x2013; from <code>v4</code> &#x2013; fixed.  <strong><em>Because of the trait system, not in spite of it</em>.</strong>  And, <strong><em>you</em></strong> can now build <strong><em>your own</em></strong> traversable types which will instantly work with all of your foldable &amp; applicative types and the foldable &amp; applicative types in language-ext.  </p><p>One thing that really frustrated me in the past was creating a type in my app domain that I then wanted to use with <code>Traverse</code>, only to remember that there was no generic traversable trait and that I&apos;d have to implement <code>Traverse</code> and <code>Sequence</code> n-times to get the same functionality as the types in language-ext.  That problem has now gone &#x2013; you still need to implement <code>Traverse</code> for your type, but just once.</p><blockquote>When you remember that <code>Traverse</code> is one of the most powerful tools in the <em>pure-functional-programming-toolkit</em> &#x2013; it means (regardless of rough edges) we&apos;ve gained some real FP superpowers here.  And these superpowers can finally land in your code-base rather than just the language-ext provided types.</blockquote><p><strong>Next up</strong>: Monads! I promised myself I&apos;d never write &apos;Yet Another Monad Tutorial&apos; &#x2013; well I guess I can&apos;t not write one now...</p><p><a href="https://paullouth.com/higher-kinds-in-csharp-with-language-ext-part-7-monads/">Part 7 - Monads.</a></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 5 - validation]]]></title><description><![CDATA[We cover one of the most useful applicative types: Validation.  It allows for the collection of multiple errors in a computation rather than just the first.]]></description><link>https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/</link><guid isPermaLink="false">65feb6992ac0342e8bc9376c</guid><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Sun, 24 Mar 2024 06:59:59 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/05/validation-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/05/validation-1.png" alt="Higher Kinds in C# with language-ext [Part 5 - validation]"><p>This is a multi-part series of articles, it&apos;s worth going back to the earlier parts if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/">Part 4 - Applicatives</a></li></ul><p>In the last article I introduced the <code>Applicative</code> trait and showed how it can be used to perform operations on &apos;<em>lifted&apos; </em>values.  The benefit of working in the &apos;lifted&apos; environment is that we don&apos;t have to unpack the values, perform the operation, and then repack the values manually &#x2013; the applicative functor does that for us.  It is the same with <code>Functor</code> &#x2013; we don&apos;t have to manually pattern-match the <code>Maybe</code> type, the <code>Either</code> type, or iterate the values in the <code>List</code> type &#x2014; the functor does that job for us.  These techniques are boilerplate removers!</p><p><em>But, where does the &apos;lifted&apos; vernacular come from?</em></p><p>Take a look at <em>Diagram 1</em> below.  At the bottom of the diagram is a blue arrow linking  <code>A</code> to <code>B</code> (which I will write <code>A &#x2192; B</code>).  The label <code>f</code> represents a single argument function that takes any value of type <code>A</code> and returns a value of type <code>B</code> &#x2013; it&apos;s a <code>Func&lt;A, B&gt;</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://paullouth.com/content/images/2024/03/Functors.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 5 - validation]" loading="lazy" width="1468" height="936" srcset="https://paullouth.com/content/images/size/w600/2024/03/Functors.png 600w, https://paullouth.com/content/images/size/w1000/2024/03/Functors.png 1000w, https://paullouth.com/content/images/2024/03/Functors.png 1468w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Diagram 1</span></figcaption></figure><p>At the top of the diagram is an equivalent of <code>A &#x2192; B</code> but with an outer <code>F</code> wrapping.  This is the applicative-functor <code>F</code>.  With functor <code>F</code> we can map <code>F&lt;A&gt;</code> to <code>F&lt;B&gt;</code> using the function <code>F&lt;f&gt;</code> &#x2013; which is <code>F&lt;Func&lt;A, B&gt;&gt;</code>.  </p><p>If you remember from, the last article, the <code>Apply</code> function looks like this:</p><pre><code class="language-csharp">K&lt;F, B&gt; Apply&lt;A, B&gt;(K&lt;F, Func&lt;A, B&gt;&gt; mf, K&lt;F, A&gt; ma)</code></pre><p>It should be fairly obvious that we can project <code>K&lt;F, A&gt; &#x2192; K&lt;F, B&gt;</code> using <code>K&lt;F, Func&lt;A, B&gt;&gt;</code> &#x2013; which maps to the top section of the diagram above.  What we&apos;re doing when we <code>Apply</code> is to do the equivalent of <code>f.Invoke(a)</code> where <code>f</code> is a regular delegate; but we&apos;re invoking for something with additional structure (<code>Maybe</code>, <code>List</code>, <code>Either</code>, ...).  So, <code>Apply</code> is just <code>Invoke</code> for <em>lifted </em>structures.</p><p>Again, &apos;lifted&apos;, why lifted?  Well, the etymology isn&apos;t entirely clear, but I believe that it&apos;s simply because when drawn out in diagram form (as above), the lifted elements are literally <em>above </em>the others.  It is also the origin of &apos;higher&apos; in higher-kinds.  </p><blockquote>It&apos;s fascinating that none of the Wikipedia references for lifting &#x2013;  whether it&apos;s <a href="https://en.wikipedia.org/wiki/Lift_(mathematics)?ref=paullouth.com">category-theory</a> or functional-programming related &#x2013; specifies the etymology.  If you have a reference to the etymology, or a better understanding of its mathematical origins, I&apos;d be very interested to see it!  </blockquote><p>Even if my definition isn&apos;t the true etymology, this is how I like to think of it.  We <em>lift</em> simple values and functions into a &apos;higher space&apos;.  And we try, as much as possible, to work in that higher-space; only coming back down when we have a concrete and robust way of doing so.  For example, if you have a <code>Maybe&lt;string&gt;</code> &#x2013; only come back down to <code>string</code> when you have a meaningful default for the <code>Nothing</code> case.  Otherwise, continue the optional computation in its higher-space using <code>Map</code>, <code>Apply</code>, etc.</p><p>The orange/vertical arrow in <em>Diagram 1</em> is the process of lifting <em>in action</em>.  The <code>Map</code> function in <code>Functor</code> <em>lifts </em>a &#x2013;  &apos;lower&apos; &#x2013; <code>Func&lt;A, B&gt;</code> function and makes it into a &apos;higher&apos; <em>lifted </em>function that can be applied to values of <code>F&lt;A&gt;</code>.  You can think of <code>Map</code> as both the operation to lift the function <em>and </em>the application of the argument (<code>Apply</code>).  Whereas <code>Apply</code> will only work with pre-lifted functions.</p><p>If we put some real types in there then it becomes a little less abstract and slightly more obvious what&apos;s really going on.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://paullouth.com/content/images/2024/03/Functors2.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 5 - validation]" loading="lazy" width="1486" height="948" srcset="https://paullouth.com/content/images/size/w600/2024/03/Functors2.png 600w, https://paullouth.com/content/images/size/w1000/2024/03/Functors2.png 1000w, https://paullouth.com/content/images/2024/03/Functors2.png 1486w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Diagram 2</span></figcaption></figure><p>There seems to be a couple of arrows missing from the diagram however.  If we can <em>lift</em> a function from being <em>just a function</em> to being an <em>embellished function.  </em>Can we do the same with <code>int &#x2192; Maybe&lt;int&gt;</code> and <code>string &#x2192; Maybe&lt;string&gt;</code>?  </p><p>Yes, we can:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://paullouth.com/content/images/2024/03/Functors3-2.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 5 - validation]" loading="lazy" width="1600" height="936" srcset="https://paullouth.com/content/images/size/w600/2024/03/Functors3-2.png 600w, https://paullouth.com/content/images/size/w1000/2024/03/Functors3-2.png 1000w, https://paullouth.com/content/images/2024/03/Functors3-2.png 1600w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Diagram 3</span></figcaption></figure><p>The two new arrows are gained from the <code>Pure</code> function that&apos;s part of the <code>Applicative</code> trait.  So, with <code>Pure</code> and <code>Map</code> we are able to lift anything we want from being a regular value or function and make them into <em>embellished </em>values and functions.</p><blockquote>I&apos;m saying &apos;embellished&apos; to mean &apos;giving extra capabilities to&apos;. So, <code>Maybe&lt;int&gt;</code> is an <code>int</code> with an <em>optionality</em> embellishment!</blockquote><p>In diagram form functors and applicative-functors become quite tame &#x2013; there isn&apos;t any great mystery behind them, they&apos;re simply mechanisms that allow us to continue working in a lifted space.  This drawing of arrows between types is the essence of Category Theory and is much simpler than the name sounds.</p><p>So, now that I&apos;ve explained the complete interface for <code>Applicative</code>, let&apos;s look at another concrete usage of applicatives: Validation.</p><p>Validation is definitely part of the &apos;awkward squad&apos;, it&apos;s never trivial to build validation into any application.  It always seems trivial on the surface, but doing it well, isn&apos;t.</p><p>Let&apos;s try and validate a credit-card and associated details using the language-ext built-in <code>Validation</code> type.  Then we can dissect how and why it works...</p><p>First, let&apos;s create the data model for what we expect the result of validating a credit-card to be:</p><pre><code class="language-csharp">// Credit care number
public record CardNumber(Seq&lt;int&gt; Number);

// Expiry date
public record Expiry(int Month, int Year);

// CVV code
public record CVV(int Number);

// Complete credit card details
public record CreditCardDetails(CardNumber CardNumber, Expiry Expiry, CVV CVV)
{
    public static CreditCardDetails Make(CardNumber cardNo, Expiry expiry, CVV cvv) =&gt;
        new (cardNo, expiry, cvv);
}
</code></pre><blockquote>I realise these are declared as records and therefore we can&apos;t control their construction; but it reduces the amount of code I need to write here!  You might want to protect their construction with classes instead.</blockquote><p>We have a card-number which holds the 16 digit credit-card number, an expiry-date in Month/Year format, a 3 digit CVV number, and a composition of all of those types, making <code>CreditCardDetails</code>.  Pretty simple.</p><p>Let&apos;s start with the simplest item, the CVV number.  The rules are:</p><ul><li>Must be all digits</li><li>Must be 3 digits in length</li></ul><p>Part of the power of writing pure functional code is its powerful composition.  Meaning we can build complex things from simple things.  So, let&apos;s start with some simple things:</p><pre><code class="language-csharp">static Validation&lt;Error, int&gt; CharToDigit(char ch) =&gt;
    ch is &gt;= &apos;0&apos; and &lt;= &apos;9&apos;
        ? Pure(ch - &apos;0&apos;)
        : Fail(Error.New($&quot;expected a digit, but got: {ch}&quot;));
</code></pre><p>Ok, so we take a <code>char</code>, check that it&apos;s one of the digit characters and if so, we return <code>Pure(ch - &apos;0&apos;)</code> &#x2013; <code>Pure</code> should have meaning to you now as the function that <em>lifts </em>values.  </p><blockquote>Because this is C# and C#&apos;s type inference is awful, <code>Pure</code> actually constructs the type <code>Pure&lt;A&gt;</code>.  This can be seen as an intermediate value until the type-system has enough information to infer.  At the point of construction the function <code>Pure(...)</code> knows nothing about <code>Error</code>, meaning we&apos;d have to specify it.  However, later, an implicit conversion can happen from<code>Pure&lt;int&gt;</code> to <code>Validation&lt;Error, int&gt;</code> and we don&apos;t need to specify the <code>Error</code> type.  </blockquote><p>If the value isn&apos;t a digit, then we call <code>Fail</code> &#x2013; which works a bit like <code>Pure</code> but for failure values.  It constructs the type <code>Fail&lt;E&gt;</code> (where <code>E</code> is the error-type).  </p><p>There are some circumstances where, even with this technique, <code>Pure</code> and <code>Fail</code> don&apos;t resolve &#x2013; and so the alternative is to directly construct the <code>Validation</code> value you need.  For example:</p><pre><code class="language-csharp">static Validation&lt;Error, int&gt; CharToDigit(char ch) =&gt;
    ch is &gt;= &apos;0&apos; and &lt;= &apos;9&apos;
        ? Validation&lt;Error, int&gt;.Success(ch - &apos;0&apos;)
        : Validation&lt;Error, int&gt;.Fail(Error.New($&quot;expected a digit, but got: {ch}&quot;));</code></pre><p>Hopefully it&apos;s clear why <code>Pure</code> and <code>Fail</code> are so useful.  It&apos;s much more elegant.  All of the core types in language-ext support implicit conversion from <code>Pure</code> and <code>Fail</code> (and have <code>SelectMany</code> overrides so they can work in LINQ expressions also).</p><p>Anyway, back to the validation!  We have a simple function that validates whether a <code>char</code> is a digit and, if so, it converts it to an <code>int</code> &#x2013; otherwise it fails with a useful error message.</p><p>If we try it out:</p><pre><code class="language-csharp">CharToDigit(&apos;x&apos;);
CharToDigit(&apos;1&apos;);</code></pre><p>We will get this output:</p><pre><code class="language-text">Fail(expected a digit, but got: x)
Success(1)</code></pre><p>Which is exactly what we want!</p><p>The CVV code is multiple digits though; so let&apos;s start leveraging the power of pure functional composition to check that all of the characters are digits:</p><pre><code class="language-csharp">static Validation&lt;Error, Iterable&lt;int&gt;&gt; ValidateAllDigits(string value) =&gt;
    value.AsIterable()
         .Traverse(CharToDigit)
         .As();
</code></pre><p>This converts the <code>string</code> to an <code>Iterable</code>, traverses each item, running the conversion.  </p><blockquote><code>Iterable</code> is a more advanced version of <code>IEnumerable</code> &#x2013; it supports: <code>Functor</code>, <code>Foldable</code>, <code>Traversable</code>, <code>Applicative</code>, <code>Monad</code>, <code>SemigroupK</code>, and <code>MonoidK</code> &#x2013; so it&apos;s like <code>IEnumerable</code> on steroids!</blockquote><p>Let&apos;s try <code>ValidateAllDigits</code> :</p><pre><code class="language-csharp">ValidateAllDigits(&quot;xy123&quot;);
ValidateAllDigits(&quot;123&quot;);</code></pre><p>This outputs:</p><pre><code class="language-text">Fail([expected a digit, but got: x, expected a digit, but got: y])
Success([1, 2, 3])</code></pre><p>Notice how we get two errors returned for <code>&quot;xy123&quot;</code> &#x2013; it is picking up both <code>x</code> and <code>y</code> as invalid digit characters and informing us of both issues.  </p><blockquote>This automatic tracking of multiple errors is enabled by the applicative capability of the <code>Validation</code> type.  We&apos;ll dissect that later.</blockquote><p>Now that we can prove all the of the characters in the <code>string</code> are digits, we can provide a wrapper function that maps the value to an <code>int</code>.</p><pre><code class="language-csharp">static Validation&lt;Error, int&gt; ValidateInt(string value) =&gt;
    ValidateAllDigits(value).Map(_ =&gt; int.Parse(value));
</code></pre><p>We don&apos;t bake this into the <code>ValidateAllDigits</code> function, because when we test the card-number later we won&apos;t convert it to an <code>int</code>.  This gives us two functions that validate, one of which maps the value.  </p><blockquote>I won&apos;t test this, because it&apos;s obvious it will work!</blockquote><p>Ok, so we can now test that the CVV is a multidigit value, but we haven&apos;t asserted that it&apos;s exactly three digits in length.  Just to show off, let&apos;s do length validation for any foldable:</p><pre><code class="language-csharp">static Validation&lt;Error, K&lt;F, A&gt;&gt; ValidateLength&lt;F, A&gt;(K&lt;F, A&gt; fa, int length)
    where F : Foldable&lt;F&gt; =&gt;
    fa.Count() == length
        ? Pure(fa)
        : Fail(Error.New($&quot;expected length to be {length}, but got: {fa.Count()}&quot;));
</code></pre><p>This leverages the built-in <code>Count()</code> extension for foldables.</p><p>But, because <code>string</code> isn&apos;t a foldable, let&apos;s create a version that turns the <code>string</code> into a foldable so it can be validated:</p><pre><code class="language-csharp">static Validation&lt;Error, string&gt; ValidateLength(string value, int length) =&gt;
    ValidateLength(value.AsIterable(), length)
        .Map(_ =&gt; value);
</code></pre><p>This is obviously overkill, but whatever, we&apos;re enjoying ourselves! </p><p>Time to test it:</p><pre><code class="language-csharp">ValidateLength(&quot;xy123&quot;, 3);
ValidateLength(&quot;123&quot;, 3);</code></pre><p>Which outputs:</p><pre><code class="language-text">Fail(expected length to be 3, but got: 5)
Success(123)
</code></pre><blockquote>Hopefully, you&apos;re also starting to see how easy this stuff is to test.  These components are all pure and have no external moving parts &#x2013; making testing trivial.</blockquote><p>So, now we have the components to assert our spec for the CVV code:</p><ul><li>Must be all digits</li><li>Must be 3 digits in length</li></ul><p>Let&apos;s compose them together:</p><pre><code class="language-csharp">static Validation&lt;Error, CVV&gt; ValidateCVV(string cvv) =&gt;
    fun&lt;int, string, CVV&gt;((code, _) =&gt; new CVV(code))
       .Map(ValidateInt(cvv))
       .Apply(ValidateLength(cvv, 3))
       .As();</code></pre><p>Here we start to see the standard applicative pattern start to emerge: a chain of <code>Map</code> follow by <code>Apply</code> &#x2013; it&apos;s something that becomes very familiar after a while.</p><p>Let&apos;s try it out:</p><pre><code class="language-csharp">ValidateCVV(&quot;xy123&quot;);
ValidateCVV(&quot;123&quot;);
</code></pre><p>It outputs:</p><pre><code class="language-text">Fail([expected a digit, but got: x, expected a digit, but got: y, expected length to be 3, but got: 5])
Success(123)
</code></pre><p>We&apos;re collecting all of the errors!  It&apos;s really starting to look more like the kind of output you&apos;d see from a compiler.  This is really powerful stuff.</p><blockquote>This is all using the built-in <code>Error</code> type.  A more advanced solution to this would be to create a bespoke error type that captures context better than raw text messages.  For example, the errors could all be grouped together and displayed much better than repeating the same &quot;expected a ...&quot; text.</blockquote><p>Now we have the CVV validator, let&apos;s look at the expiry date.  Our rules will be:</p><ul><li>Must be in the format <code>&lt;MM&gt;[&apos;\&apos; | &apos;/&apos; | &apos;-&apos; | &apos; &apos;]&lt;YYYY&gt;</code> &#x2013; some examples:<ul><li><code>12-2024</code></li><li><code>01/2025</code></li><li><code>06 2029</code></li></ul></li><li>The first part (the month) must be an integer from <code>1 &#x2013; 12</code></li><li>The second part must be:<ul><li>A four digit integer</li><li>Equal to this year or a year in the next 10</li></ul></li></ul><blockquote>We already have the <code>ValidateInt</code> function from earlier, we can re-use that.  </blockquote><p>The next thing we&apos;re going to need is to check whether the parts of the date (the month and the year) are in range.  The range is from <em>now</em> to ten years in the future.  Dates are a little tricky, so instead of making the validator too complex, let&apos;s extend the <code>Expiry</code> type to act like a complex number that we can do range based operations on:</p><pre><code class="language-csharp">// Expiry date
public record Expiry(int Month, int Year) :
    IAdditionOperators&lt;Expiry, Expiry, Expiry&gt;,
    IComparisonOperators&lt;Expiry, Expiry, bool&gt;
{
    public static readonly Expiry OneMonth = new (1, 0); 
    
    public static Expiry operator +(Expiry left, Expiry right)
    {
        var m = left.Month + right.Month;
        var y = left.Year + right.Year;
        while (m &gt; 12) 
        {
          m -= 12;
          y++;
        }
        return new Expiry(m, y);
    }

    public static bool operator &gt;(Expiry left, Expiry right) =&gt;
        left.Year &gt; right.Year ||
        left.Year == right.Year &amp;&amp; left.Month &gt; right.Month;

    public static bool operator &gt;=(Expiry left, Expiry right) =&gt;
        left.Year &gt; right.Year ||
        left.Year == right.Year &amp;&amp; left.Month &gt;= right.Month;

    public static bool operator &lt;(Expiry left, Expiry right) =&gt;
        left.Year &lt; right.Year ||
        left.Year == right.Year &amp;&amp; left.Month &lt; right.Month;
    
    public static bool operator &lt;=(Expiry left, Expiry right) =&gt;
        left.Year &lt; right.Year ||
        left.Year == right.Year &amp;&amp; left.Month &lt;= right.Month;

    public static Expiry Now
    {
        get
        {
            var now = DateTime.Now;
            return new Expiry(now.Month, now.Year);
        }
    }

    public static Range&lt;Expiry&gt; NextTenYears =&gt;
        LanguageExt.Range.fromMinMax(Now, Now + new Expiry(0, 10), new Expiry(1, 0));
}</code></pre><p>I won&apos;t go into too much detail on that because it&apos;s pretty regular C#.  But, the things to note are that it now supports the addition operator that understands how to add months and years.  And it can do comparisons that take into account the month and year correctly.  Finally, it exposes a language-ext <code>Range</code> that is from <code>Now</code> to 10 years from now.</p><p>That <code>NextTenYears</code> range is what we will validate against...</p><p>Let&apos;s create a general range validator:</p><pre><code class="language-csharp">static Validation&lt;Error, A&gt; ValidateInRange&lt;A&gt;(A value, Range&lt;A&gt; range)
    where A : IAdditionOperators&lt;A, A, A&gt;,
              IComparisonOperators&lt;A, A, bool&gt; =&gt;
    range.InRange(value)
        ? Pure(value)
        : Fail(Error.New($&quot;expected value in range of {range.From} to {range.To}, but got: {value}&quot;));
</code></pre><p>It takes a value and a range and tests if the value is within the range.  Let&apos;s test it:</p><pre><code class="language-csharp">ValidateInRange(new Expiry(10, 2024), Expiry.NextTenYears);
ValidateInRange(new Expiry(2, 2034), Expiry.NextTenYears);
ValidateInRange(new Expiry(10, 2034), Expiry.NextTenYears);
ValidateInRange(new Expiry(1, 2023), Expiry.NextTenYears);</code></pre><p>It outputs:</p><pre><code class="language-test">Success(10/2024)
Success(2/2034)
Fail(expected value in range of 3/2024 to 3/2034, but got: 10/2034)
Fail(expected value in range of 3/2024 to 3/2034, but got: 1/2023)</code></pre><p>Nice!  It&apos;s always better if you can make a complex pairing like month and year work together in a single value-type.  Of course we could have leveraged <code>DateTime</code> but this is more precise and declarative.</p><p>Now let&apos;s compose that into something that validates a month and a year string:</p><pre><code class="language-csharp">static Validation&lt;Error, Expiry&gt; ValidateExpiryDate(string expiryDate) =&gt;
    expiryDate.Split([&apos;\\&apos;, &apos;/&apos;, &apos;-&apos;, &apos; &apos;]) switch
    {
        [var month, var year] =&gt;
            from my in ValidateInt(month) &amp; ValidateInt(year)
            let exp = new Expiry(my[0], my[1])
            from _  in ValidateInRange(exp, Expiry.NextTenYears)
            select exp,
        
        _ =&gt; Fail(Error.New($&quot;expected expiry-date in the format: MM/YYYY, but got: {expiryDate}&quot;))
    };</code></pre><p>This is a little bit harder to parse.  First we spit the <code>expiryDate</code> string.  We are expecting two parts, so we pattern match to extract the <code>month</code> and <code>year</code> parts.  If the match fails then we yield an explanatory error.  </p><p>We then call <code>ValidateInt</code> twice.  One for <code>month</code> and one for <code>year</code>.  They are composed using the <code>&amp;</code> operator.  When you find that all terms of an <code>Apply</code> expression yield the same type then you can use <code>&amp;</code> or <code>|</code> to check for any errors.  <code>&amp;</code> will collect the results of the operands into a <code>Seq</code> (if all are successful), whereas <code>|</code> will continue if either operand is successful, but if both fail then it will collect all of the errors.</p><blockquote>NOTE: The <code>|</code> operator works slightly differently in <code>v5</code> compared to <code>v4</code>.  <code>v4</code> was closer to the <code>&amp;</code> behaviour.  So, when migrating it is worth finding all usages of <code>Validation</code> and migrating <code>|</code> to <code>&amp;</code>.</blockquote><p>That means <code>my</code> is a <code>Seq&lt;int&gt;</code> if both the <code>month</code> and the <code>year</code> validate as integers.  We can then create a new <code>Expiry</code> and check that the expiry date is within the valid range.</p><p>Let&apos;s test...</p><pre><code class="language-csharp">ValidateExpiryDate(&quot;10-2024&quot;);
ValidateExpiryDate(&quot;02-2034&quot;);
ValidateExpiryDate(&quot;10/2034&quot;);
ValidateExpiryDate(&quot;1/2023&quot;);
ValidateExpiryDate(&quot;1X2023&quot;);
ValidateExpiryDate(&quot;02-F00&quot;);
</code></pre><p>It outputs:</p><pre><code class="language-text">Success(10/2024)
Success(2/2034)
Fail(expected value in range of 3/2024 to 3/2034, but got: 10/2034)
Fail(expected value in range of 3/2024 to 3/2034, but got: 1/2023)
Fail(expected expiry-date in the format: MM/YYYY, but got: 1X2023)
Fail(expected a digit, but got: F)</code></pre><p>Yeah, this is good!  Meaningful validation output.</p><p>Now we need to validate the main credit-card number, here&apos;s the final function:</p><pre><code class="language-csharp">static Validation&lt;Error, CardNumber&gt; ValidateCardNumber(string cardNo) =&gt;
    (ValidateAllDigits(cardNo), ValidateLength(cardNo, 16))
        .Apply((digits, _) =&gt; digits.ToSeq())
        .Bind(ValidateLuhn)
        .Map(digits =&gt; new CardNumber(digits))
        .As();</code></pre><p>We&apos;ve already seen the <code>ValidateAllDigits</code> and the <code>ValidateLength</code> validators, what we haven&apos;t seen is <code>Apply</code> used on a tuple of <code>Validation</code> types. This is an alternative approach to calling <code>Apply</code> &#x2013; for some circumstances it&apos;s more elegant as you don&apos;t need to provide the type-signature of the lambda.  </p><blockquote>NOTE: Sometimes the tuple-based <code>Apply</code> doesn&apos;t pass the C# type-checker.  The <code>Apply</code> methods extend <code>(K&lt;F, A&gt;, F&lt;F, B&gt;, ...)</code> and it seems sometimes C# doesn&apos;t want to coerce the value to its underlying interface &#x2013; I&apos;m not sure the exact rules around this, I will dig some more, but if you face this problem you can just chain the <code>Map</code> and <code>Apply</code> functions as seen in the examples up to now.</blockquote><p><code>ValidateLuhn</code> is also called sequentially using the monadic <code>Bind</code> operation.  We&apos;ll discuss monads in a later article &#x2013; but just know that <code>Bind</code> operation runs after we&apos;ve validated that the card-number is 16-digits in length.</p><p>What about <code>ValidateLuhn</code> &#x2013;  what does it do?  Let&apos;s look at it:</p><pre><code class="language-csharp">static Validation&lt;Error, Seq&lt;int&gt;&gt; ValidateLuhn(Seq&lt;int&gt; digits)
{
    int checkDigit = 0;
    for (int i = digits.Length - 2; i &gt;= 0; --i)
    {
        checkDigit += ((i &amp; 1) is 0) switch
                      {
                          true  =&gt; digits[i] &gt; 4 ? digits[i] * 2 - 9 : digits[i] * 2,
                          false =&gt; digits[i]
                      };
    }

    return (10 - checkDigit % 10) % 10 == digits.Last
               ? Pure(digits)
               : Fail(Error.New(&quot;invalid card number&quot;));
}</code></pre><p>This is an implementation of the <a href="https://en.wikipedia.org/wiki/Luhn_algorithm?ref=paullouth.com">Luhn algorithm</a>, which is essentially a check-sum for credit-card numbers.  It makes sure the person who typed it in didn&apos;t make a mistake.  I haven&apos;t modified it much from the version on the Wikipedia page, I&apos;ve simply made it accept a <code>Seq&lt;int&gt;</code> and return a <code>Validation</code> depending on whether the check-sum succeeds or not.  So, I won&apos;t dwell on this implementation too much.</p><p>It does however mean that <code>ValidateCardNumber</code> should check that each character is a digit, that the length of the digits is 16 characters, and that the digits pass the Luhn algorithm check-sum.  Let&apos;s try it:</p><pre><code class="language-csharp">ValidateCardNumber(&quot;4560005094752584&quot;);
ValidateCardNumber(&quot;00000&quot;);
ValidateCardNumber(&quot;000000000000000x&quot;);
ValidateCardNumber(&quot;0000000000000000x&quot;);</code></pre><p>It outputs:</p><pre><code class="language-csharp">Success([4, 5, 6, 0, 0, 0, 5, 0, 9, 4, 7, 5, 2, 5, 8, 4])
Fail(expected length to be 16, but got: 5)
Fail(expected a digit, but got: x)
Fail([expected a digit, but got: x, expected length to be 16, but got: 17])</code></pre><blockquote>The credit card number is a fake btw!</blockquote><p>So, we have all of the component parts now.  We should be able to do the final validator:</p><pre><code class="language-csharp">public static Validation&lt;Error, CreditCardDetails&gt; Validate(string cardNo, string expiryDate, string cvv) =&gt;
    fun&lt;CardNumber, Expiry, CVV, CreditCardDetails&gt;(CreditCardDetails.Make)
       .Map(ValidateCardNumber(cardNo))
       .Apply(ValidateExpiryDate(expiryDate))
       .Apply(ValidateCVV(cvv))
       .As();
</code></pre><p>Here we get to see the pure functional composition really starting to open up.  I really love seeing this stuff.  We have combined small components (like digit-validators, integer-validators, range-validators, etc. into larger components, like <code>ValidateCardNumber</code>, <code>ValidateExpiryDate</code>, and <code>ValidateCVV</code>.  And now, we get to compose those bigger components into an even bigger component.  </p><p>It&apos;s pure all the way down!  It&apos;s robust and error free all the way down!  It&apos;s turtles all the way down!  These things stick together like Lego &#x2013; once you&apos;ve built your core components then they all stack up beautifully.</p><p>Let&apos;s do the final test:</p><pre><code class="language-csharp">Validate(&quot;4560005094752584&quot;, &quot;12-2024&quot;, &quot;123&quot;);
Validate(&quot;00000&quot;, &quot;00-2345&quot;, &quot;XYZ&quot;);
</code></pre><p>It outputs:</p><pre><code class="language-text">Success(CreditCard([4, 5, 6, 0, 0, 0, 5, 0, 9, 4, 7, 5, 2, 5, 8, 4], 12/2024, 123))

Fail([expected length to be 16, but got: 5, expected value in range of 3/2024 to 3/2034, but got: 0/2345, expected a digit, but got: W, expected a digit, but got: X, expected a digit, but got: Y, expected a digit, but got: Z])
</code></pre><p>That all works exactly as it should, we have lots of errors that show at a fine-grained level what the issues were with the credit-card details.  The thing is, maybe it&apos;s too fine-grained?  Do we really care about individual digits being letters?  Are the error messages descriptive enough?  I&apos;d say &quot;no&quot;.  We can do better.</p><p>When we&apos;re parsing a <code>char</code> to see if it&apos;s a digit we have no idea that it&apos;s part of a CVV code or card-number, so we can&apos;t give context.  But we can add that context higher up the stack: This is where <code>MapFail</code> comes in.  It allows you to take an error and provide more context higher up the stack where you have it.  </p><p>Here&apos;s a version of <code>ValidateCVV</code> which overrides the simpler errors messages and provides something contextual:</p><pre><code class="language-csharp">static Validation&lt;Error, CVV&gt; ValidateCVV(string cvv) =&gt;
    fun&lt;int, string, CVV&gt;((code, _) =&gt; new CVV(code))
       .Map(ValidateInt(cvv).MapFail(_ =&gt; Error.New(&quot;CVV code should be a number&quot;)))
       .Apply(ValidateLength(cvv, 3).MapFail(_ =&gt; Error.New(&quot;CVV code should be 3 digits in length&quot;)))
       .As(); 
</code></pre><p>You could do other things like create <code>Error</code> hierarchies where the inner-errors hold the more fine-grained errors and they&apos;re wrapped in a more contextual error.  This can be great for debugging purposes &#x2013; where you want to carry the raw info but also give friendly errors to end-users.</p><p>For example, if we take the <code>ValidateCardNumber</code> from earlier and use <code>MapFail</code>:</p><pre><code class="language-csharp">static Validation&lt;Error, CardNumber&gt; ValidateCardNumber(string cardNo) =&gt;
    (ValidateAllDigits(cardNo), ValidateLength(cardNo, 16))
        .Apply((digits, _) =&gt; digits.ToSeq())
        .Bind(ValidateLuhn)
        .Map(digits =&gt; new CardNumber(digits))
        .As()
        .MapFail(e =&gt; Error.New(&quot;card number not valid&quot;, e)); </code></pre><p>The final <code>MapFail</code> there will capture any failure and wrap it up in a new error that simply has the message <code>&quot;card number not valid&quot;</code> &#x2013; but it carries the details in its <code>Inner</code> property.  </p><p>If we run the test from before with these new changes:</p><pre><code class="language-csharp">Validate(&quot;00000&quot;, &quot;00-2345&quot;, &quot;WXYZ&quot;)</code></pre><p>We get:</p><pre><code class="language-text">Fail([card number not valid, expected value in range of 3/2024 to 3/2034, but got: 0/2345, CVV code should be a number, CVV code should be 3 digits in length])</code></pre><p>So now we have 4 errors, each explaining clearly what the problem is, but there is also some inner errors that give even more context if needed.  Nice!</p><p>All of this behaviour is enabled by applicatives.  If you remember from the last article the <code>IO</code> monad was able to run things in parallel (in its <code>Apply</code> function).  It was leveraging the fact that it could wait for the <em>successful</em> result of two operations before applying the values. <code>Validation</code> works the opposite way, it waits for the <em>failure </em>results of two operations and combines them.</p><p>Here is the <code>Apply</code> trait implementation for <code>Validation</code>:</p><pre><code class="language-csharp">static K&lt;Validation&lt;FAIL&gt;, B&gt; Applicative&lt;Validation&lt;FAIL&gt;&gt;.Apply&lt;A, B&gt;(
    K&lt;Validation&lt;FAIL&gt;, Func&lt;A, B&gt;&gt; mf,
    K&lt;Validation&lt;FAIL&gt;, A&gt; ma) =&gt;
    mf switch
    {
        Validation.Success&lt;FAIL, Func&lt;A, B&gt;&gt; (var f) =&gt;
            ma switch
            {
                Validation.Success&lt;FAIL, A&gt; (var a) =&gt;
                    Validation&lt;FAIL, B&gt;.Success(f(a)),

                Validation.Fail&lt;FAIL, A&gt; (var e) =&gt;
                    Validation&lt;FAIL, B&gt;.Fail(e),

                _ =&gt;
                    Validation&lt;FAIL, B&gt;.Fail(FAIL.Empty)
            },

        Validation.Fail&lt;FAIL, Func&lt;A, B&gt;&gt; (var e1) =&gt;
            ma switch
            {
                Validation.Fail&lt;FAIL, A&gt; (var e2) =&gt;
                    Validation&lt;FAIL, B&gt;.Fail(e1 + e2),

                _ =&gt;
                    Validation&lt;FAIL, B&gt;.Fail(e1)

            },
        _ =&gt; Validation&lt;FAIL, B&gt;.Fail(FAIL.Empty)
    };</code></pre><p>If you follow the pattern-match through the two <code>Validation.Fail</code> cases, you&apos;ll see it calls <code>e1 + e2</code>  which are the two error values being combined into one.</p><p>The other thing to note is that <code>Validation</code> can have any value for its <code>FAIL</code> case as long as it&apos;s a <code>Monoid</code> (go back to the first article in this series for a reminder about monoids).  So, if you want to implement a bespoke error type then make sure you make it monoidal.</p><p>Ok, so this article definitely went on longer than I expected! I did feel it was important to really see the benefits of the applicative-functor approach though &#x2013;  because I think it&apos;s a trait that gets overlooked quite often &#x2013; mostly because it&apos;s not as pretty as functors and monads, but the compositional power of applicatives should not be ignored!</p><blockquote>Because there&apos;s a lot of code in this article I&apos;ve <a href="https://github.com/louthy/language-ext/tree/main/Samples/CreditCardValidation?ref=paullouth.com" rel="noreferrer">uploaded it all to a sample in the language-ext repo</a> for your convenience.</blockquote><p>Next up, <a href="https://paullouth.com/higher-kinds-in-csharp-part6-traversables/">traversables...</a> </p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 4 - applicatives]]]></title><description><![CDATA[Applicatives are not often talked about outside of Haskell-land, but are extremely powerful compositional tools.  ]]></description><link>https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/</link><guid isPermaLink="false">65e5f96a2ac0342e8bc9342f</guid><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><category><![CDATA[functor]]></category><category><![CDATA[hkt]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[traits]]></category><category><![CDATA[applicatives]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Tue, 12 Mar 2024 10:00:24 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/05/applicatives-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/05/applicatives-1.png" alt="Higher Kinds in C# with language-ext [Part 4 - applicatives]"><p>This is a multi-part series of articles, it&apos;s worth going back to the earlier parts if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/">Part 3 - Foldables</a></li></ul><p>Let&apos;s now look at the next trait-type: <code>Applicative</code>.  Or, to give it its full name: <em>Applicative Functor</em>...  </p><p>Applicative Functors are a &apos;<em>stepping stone&apos;</em> between functors and monads &#x2013; they&apos;re probably less well-known but have some interesting properties of their own when it comes to <em>lifted expression evaluation</em>.  Two of the major uses in language-ext is to enable <em>automatic parallel processing of effectful computations</em> and to <em>automatically collect multiple errors when validating</em>.  Those aren&apos;t the only usages &#x2013;  all of the higher-kinded-types, including the collection-types, have the applicative traits.</p><p>If we take a look back at <em>Functor</em>, it has a single method in its trait: <code>Map</code>.  <code>Map</code> takes a regular function <code>Func&lt;A, B&gt;</code> and allows it to run on the bound-values <em>within </em>the functor, effectively making a <code>Func&lt;A, B&gt;</code> into a <code>Func&lt;F&lt;A&gt;, F&lt;B&gt;&gt;</code>.</p><p>For example, if I have an <code>A</code> then a <code>Func&lt;A, B&gt;</code> will get me a <code>B</code>.  This is basic stuff.  But, if I have one or more <code>A</code> values within an <code>F&lt;A&gt;</code>, I want to be able to apply the <code>Func&lt;A, B&gt;</code> to the bound values to transform them: that&apos;s what <code>Map</code> does.  It means that <em>every function that&apos;s ever been written </em>to work with single values of <code>A</code> can now work with any type that is a &apos;container&apos; of zero or more values of <code>A</code>.</p><blockquote>So, for <code>List&lt;A&gt;</code> we get to turn it into a <code>List&lt;B&gt;</code> by applying <code>Func&lt;A, B&gt;</code> with <code>Map</code>.</blockquote><p>The function passed to map has a single argument - it&apos;s a unary operation.  So, simple operations like this are easily achievable:</p><pre><code class="language-csharp">// Simple unary function
static bool Not(bool x) =&gt;
    !x; 

// Mapping of a list of booleans
var xs = new List&lt;bool&gt;([true, false, true]);
var ys = xs.Map(Not);

// Mapping a boolean Maybe
var mx = new Just&lt;bool&gt;(true);
var my = mx.Map(Not);
</code></pre><p>What happens if we want to do a binary operation?  How would we achieve that?</p><p>Let&apos;s take a look at a simple mathematical expression:</p><pre><code class="language-text">1 &#xD7; 2 + 3 &#xD7; 4</code></pre><p>What if the operands weren&apos;t just pure values, but were instead lifted up into a <code>Maybe</code>?  </p><pre><code class="language-csharp">Just(1) * Just(2) + Just(3) * Just(4)</code></pre><p>Could we still operate on those values without losing the semantics of the <code>Maybe</code> structure &#x2013; namely that the values are optional?</p><p>If the values were <code>int?</code> then we may write some code like this:</p><pre><code class="language-csharp">int? w = ...;
int? x = ...;
int? y = ...;
int? z = ...;

if(w.HasValue &amp;&amp; 
   x.HasValue &amp;&amp; 
   y.HasValue &amp;&amp; 
   z.HasValue)
{
   return w.Value * x.Value + y.Value * z.Value;
}
else
{
   return null;
}</code></pre><p>Plenty of boilerplate and plenty of opportunities to make a mistake.</p><blockquote>WARNING: This next section is becomes a bit of a mindfuck before it gets good.  Stick with it!</blockquote><p>With <code>Maybe&lt;int&gt;</code> what could we do?  So far, we&apos;ve only got support for <code>Map</code> and <code>Fold</code> behaviours.  <code>Map</code> takes unary function arguments, but we have binary functions (<code>+</code> and <code>&#xD7;</code>), how can we make them unary?  Simply, we can <a href="https://en.wikipedia.org/wiki/Currying?ref=paullouth.com">curry</a> them:</p><pre><code class="language-csharp">// Binary addition function
static int Add(int x, int y) =&gt;
    x + y; 

// Binary multiplication function
static int Multiply(int x, int y) =&gt;
    x * y; 

// Curry the functions
var add = curry&lt;int, int, int&gt;(Add);           // (int x) =&gt; (int y) =&gt; x + y
var multiply = curry&lt;int, int, int&gt;(Multiply); // (int x) =&gt; (int y) =&gt; x * y</code></pre><p>Currying creates a series of nested lambdas rather than a single &apos;tuple&apos; lambda.  This allows us to <a href="https://en.wikipedia.org/wiki/Partial_application?ref=paullouth.com">partially apply</a> our arguments to the functions.</p><pre><code class="language-csharp">var add10 = add(10);      // Func&lt;int, int&gt;
var result = add10(20);   // 30</code></pre><p>Partial application allows us to progressively feed values into the function without the need to collect all of the argument the values upfront.</p><p>Let&apos;s now create the four terms of our expression:</p><pre><code class="language-csharp">var mw = new Just&lt;int&gt;(1);
var mx = new Just&lt;int&gt;(2);
var my = new Just&lt;int&gt;(3);
var mz = new Just&lt;int&gt;(4);</code></pre><p>And then start multiplying with <code>Map</code>:</p><pre><code class="language-csharp">K&lt;Maybe, Func&lt;int, int&gt;&gt; r1 = mw.Map(multiply);
</code></pre><p>What we end up here is the value <em>inside</em> <code>mw</code> being partially applied to the <code>multiply</code> function &#x2013; it returns a function that gets wrapped back up inside a <code>Maybe&lt;Func&lt;int, int&gt;&gt;</code> &#x2013; if we can just supply one more argument then we have the first multiplication expression done:</p><pre><code class="language-csharp">var r2 = r1.Map(f =&gt; mx.Map(f));   // K&lt;Maybe, K&lt;Maybe, int&gt;&gt;</code></pre><p>So, we call <code>Map</code> on <code>r1</code> (which has a <code>Func&lt;int, int&gt;</code> inside), we then pass that to <code>mx.Map</code> &#x2013; which completes the multiplication operation.  </p><p>But, we have problem! We want our <code>Map</code> operation to be <code>int &#x2192; int</code>, we were not expecting another <code>Maybe&lt;int&gt;</code> to be returned.  However, because of our nesting of <code>Map</code>operations we cause the final <code>r2</code> result to be <em>two </em>nested maybes.  This isn&apos;t good!</p><p>If we take it further and try to do the full expression: <code>1 x 2 + 3 x 4</code> then it gets worse!</p><pre><code class="language-csharp">var lhs = mw.Map(multiply).Map(f =&gt; mx.Map(f));
var rhs = my.Map(multiply).Map(f =&gt; mz.Map(f));
var res = lhs.Map(l =&gt; l.Map(add).Map(f =&gt; rhs.Map(r =&gt; r.Map(f))));</code></pre><p>Would you like to guess what <code>res</code> is?  You got it:</p><pre><code class="language-csharp">K&lt;Maybe, K&lt;Maybe, K&lt;Maybe, K&lt;Maybe, int&gt;&gt;&gt;&gt; res;  // Ouch!</code></pre><p>Four nested maybes!  So, not only do we not have the result we want, it&apos;s truly horrible to write.  We need a better solution, we need <em>applicative functors</em>!</p><pre><code class="language-csharp">public interface Applicative&lt;F&gt; : Functor&lt;F&gt;
    where F : Applicative&lt;F&gt;
{
    public static abstract K&lt;F, A&gt; Pure&lt;A&gt;(A value);

    public static abstract K&lt;F, B&gt; Apply&lt;A, B&gt;(K&lt;F, Func&lt;A, B&gt;&gt; mf, K&lt;F, A&gt; ma);
}</code></pre><p>Take a look at the <code>Apply</code> function signature.  Does is remind you of anything?  Let&apos;s take a look at <code>Functor</code> again:</p><pre><code class="language-csharp">public interface Functor&lt;F&gt;  
    where F : Functor&lt;F&gt;
{
    public static abstract K&lt;F, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;F, A&gt; ma);
}</code></pre><blockquote>By the way, I am now using the definition from language-ext, where <code>K&lt;F, A&gt;</code> is the last argument in the argument-list for <code>Map</code>.</blockquote><p>Both <code>Map</code> and <code>Apply</code> look almost exactly the same.  The only difference is that the <code>Func&lt;A, B&gt;</code> is also <em>lifted</em> in the applicative <code>Apply</code> function (i.e. it&apos;s wrapped up in a <code>K&lt;F, ...&gt;</code>).</p><p>But, if you look at the, earlier, first step of trying to partially-apply the <code>mulitply</code> function:</p><pre><code class="language-csharp">K&lt;Maybe, Func&lt;int, int&gt;&gt; r1 = mw.Map(multiply);</code></pre><p>Then you&apos;ll notice that it too is a <code>Func</code> that is <em>lifted</em> into the <code>Maybe</code> structure.  Looks like we might be on something here!</p><p>Let&apos;s implement <code>Applicative</code> for <code>Maybe</code>:</p><pre><code class="language-csharp">public class Maybe : 
    Foldable&lt;Maybe&gt;,
    Applicative&lt;Maybe&gt;
{
    public static K&lt;Maybe, A&gt; Pure&lt;A&gt;(A value) =&gt;
        new Just&lt;A&gt;(value);

    public static K&lt;Maybe, B&gt; Apply&lt;A, B&gt;(K&lt;Maybe, Func&lt;A, B&gt;&gt; mf, K&lt;Maybe, A&gt; ma) =&gt;
        mf switch
        {
            Just&lt;Func&lt;A, B&gt;&gt; (var f) =&gt; 
                ma switch
                {
                    Just&lt;A&gt;(var a) =&gt;
                        new Just&lt;B&gt;(f(a)),
                    
                    Nothing&lt;A&gt; =&gt;
                        new Nothing&lt;B&gt;()
                },
            Nothing&lt;Func&lt;A, B&gt;&gt; =&gt;
                new Nothing&lt;B&gt;()
        };
    
    public static K&lt;Maybe, B&gt; Map&lt;A, B&gt;(Func&lt;A, B&gt; f, K&lt;Maybe, A&gt; ma) =&gt;
        ma switch
        {
            Just&lt;A&gt; (var x) =&gt; new Just&lt;B&gt;(f(x)),
            Nothing&lt;A&gt;      =&gt; new Nothing&lt;B&gt;()
        };
    
    public static S FoldWhile&lt;A, S&gt;(
        Func&lt;A, Func&lt;S, S&gt;&gt; f,
        Func&lt;(S State, A Value), bool&gt; predicate,
        S state,
        K&lt;Maybe, A&gt; ta) =&gt;
        ta switch
        {
            Just&lt;A&gt; (var x) when predicate((state, x)) =&gt; f(x)(state),
            _                                          =&gt; state
        };
    
    public static S FoldBackWhile&lt;A, S&gt;(
        Func&lt;S, Func&lt;A, S&gt;&gt; f, 
        Func&lt;(S State, A Value), bool&gt; predicate, 
        S state, 
        K&lt;Maybe, A&gt; ta) =&gt;
        Fold(s =&gt; a =&gt; f(a)(s), state, ta);
}</code></pre><blockquote>I have implemented the traits as they exist in language-ext.  So, you&apos;ll notice the new implementation of <code>Map</code> reflects the interface in language-ext, rather than the implementations from the earlier articles.  Additionally, you should see that <code>Fold</code> and <code>FoldBack</code> are now <code>FoldWhile</code> and <code>FoldWhileBack</code> &#x2013;  these are the actual abstract methods used in the language-ext interface: it allows for more optimal default implementations of the other trait methods, like <code>Exists</code>, <code>ForAll</code>, <code>IsEmpty</code>, etc.   </blockquote><p>Let&apos;s look at the implementation of <code>Apply</code>:</p><pre><code class="language-csharp">public static K&lt;Maybe, B&gt; Apply&lt;A, B&gt;(K&lt;Maybe, Func&lt;A, B&gt;&gt; mf, K&lt;Maybe, A&gt; ma) =&gt;
    mf switch
    {
        Just&lt;Func&lt;A, B&gt;&gt; (var f) =&gt; 
            ma switch
            {
                Just&lt;A&gt;(var a) =&gt;
                    new Just&lt;B&gt;(f(a)),
                
                Nothing&lt;A&gt; =&gt;
                    new Nothing&lt;B&gt;()
            },
        Nothing&lt;Func&lt;A, B&gt;&gt; =&gt;
            new Nothing&lt;B&gt;()
    };</code></pre><p>It&apos;s a simple nested pattern-match that tries to extract the <code>Func&lt;A, B&gt;</code> from <code>mf</code> and the <code>A</code> from <code>ma</code>.  If either of them are in a <code>Nothing</code> state then we get <code>Nothing</code> returned.  Which makes sense &#x2013; we can&apos;t invoke the function if we don&apos;t have the function or if we don&apos;t have the argument to pass to the function.</p><p>But, if both <code>mf</code> and <code>ma</code> are in a <code>Just</code> state then we can simply invoke the function and then wrap it back up inside a <code>Maybe</code> by passing the result to the constructor for <code>Just</code>.  </p><p>Let&apos;s update our extension methods to allow us to use the new applicative <code>Apply</code> method.  We&apos;ll also add a new <code>Map</code> extension with the arguments flipped (I mentioned in an earlier episode that I would demonstrate why the arguments are flipped &#x2013; you&apos;re about to see why it works this way):</p><pre><code class="language-csharp">// Functor map (notice that `this` is a `Func`)
public static K&lt;F, B&gt; Map&lt;F, A, B&gt;(this Func&lt;A, B&gt; f, K&lt;F, A&gt; ma) 
    where F : Functor&lt;F&gt; =&gt;
    F.Map&lt;A, B&gt;(f, ma);

// Applicative apply
public static K&lt;F, B&gt; Apply&lt;F, A, B&gt;(this K&lt;F, Func&lt;A, B&gt;&gt; mf, K&lt;F, A&gt; ma) 
    where F : Applicative&lt;F&gt; =&gt;
    F.Apply&lt;A, B&gt;(mf, ma);</code></pre><p>If you remember our first attempt at multiplying two <code>Maybe&lt;int&gt;</code> values together looked like this:</p><pre><code class="language-csharp">var r = mw.Map(multiply).Map(f =&gt; mx.Map(f));</code></pre><p>And that resulted in a nested <code>Maybe&lt;Maybe&lt;int&gt;&gt;</code>.  Instead, we can now use the <code>Apply</code> function (along with the flipped-argument <code>Map</code>) to avoid the nesting:</p><pre><code class="language-csharp">var r = multiply.Map(mw).Apply(mx)   // K&lt;Maybe, int&gt;</code></pre><p>And that works!  Returning a <code>K&lt;Maybe, int&gt;</code> rather than the double-nested maybe we saw earlier.  The flipped-argument <code>Map</code> function also allows us to move the function-argument to the left-most position in the expression, it is then followed by <code>n</code> arguments that are fluently fed into the function.  This just reads better.</p><p>For those that know Haskell, you&apos;ll recognise this technique.  In Haskell it would look like this:</p><pre><code class="language-haskell">let r = multiply &lt;$&gt; mw &lt;*&gt; mx</code></pre><blockquote>I would love to be able to use operators to make this a little more elegant in C#, but operators can&apos;t be parametrically polymorphic and so the only way is to use this fluent style.</blockquote><p>If you have functions with even more arguments then you can simply chain more calls to <code>Apply</code> and it will <em>just work.</em></p><p>Now lets do the applicative-version of the imperative nullable-expression from earlier:</p><pre><code class="language-csharp">var lhs = multiply.Map(mw).Apply(mx);
var rhs = multiply.Map(my).Apply(mz);
var res = add.Map(lhs).Apply(rhs);
</code></pre><p>It is more concise than the imperative version, it&apos;s less error prone, and it supports every single applicative type ever written.  So, we can run this with <code>Either</code>, <code>Option</code>, <code>Seq</code>, etc.  </p><p>It&apos;s not quite as easy to read which is definitely the downside to using applicatives in C#.  Most applicatives are also monads and monads (in C#) are &apos;LINQ friendly&apos;. Which means we could have just written:</p><pre><code class="language-csharp">var res = from w in mw
          from x in mx
          from y in my
          from z in mz
          select w * x + y * z;</code></pre><p>It&apos;s probably easier to read and doesn&apos;t need any special currying of functions.  So, what is it that applicatives have over monads?  Namely, monads are about <em>sequential operations </em>&#x2013; we can only get each operand of the final expression in-sequence, first the <code>w</code>, then the <code>x</code>,  then the <code>y</code>, then the <code>z</code>, then we return the result (if all succeeded).  If any fail we return <em>immediately </em>and don&apos;t process the rest.  </p><p>Applicatives however do not have sequential processing semantics.  In fact, they&apos;re the opposite.</p><p>Let&apos;s take a look at the earlier mathematical expression in tree form.  We can see that there are two main branches that are entirely independent of each other.  We <em>could </em>calculate the left-hand-side in-parallel to the processing of the right-hand-side before applying the values to the addition function.</p><figure class="kg-card kg-image-card"><img src="https://paullouth.com/content/images/2024/03/Expression.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 4 - applicatives]" loading="lazy" width="1298" height="968" srcset="https://paullouth.com/content/images/size/w600/2024/03/Expression.png 600w, https://paullouth.com/content/images/size/w1000/2024/03/Expression.png 1000w, https://paullouth.com/content/images/2024/03/Expression.png 1298w" sizes="(min-width: 720px) 720px"></figure><p>Because applicatives get access to both their function and its argument at the <em>same time</em>, they&apos;re able to follow a strategy where the operands are calculated independently. </p><p>You can see this in the <code>Apply</code> implementation for IO effect type: </p><pre><code class="language-csharp">public static IO&lt;B&gt; Apply&lt;A, B&gt;(this IO&lt;Func&lt;A, B&gt;&gt; ff, IO&lt;A&gt; fa) =&gt;
    from tf in ff.Fork()
    from ta in fa.Fork()
    from f in tf.Await
    from a in ta.Await
    select f(a);
</code></pre><p>Notice how it forks both the function IO and the argument IO.  That means they can run in parallel whilst further down the expression awaits both IO operations to complete.  If you use functions with more arguments (and therefore chain more <code>Apply</code> calls) then each argument runs in parallel and the final function invocation only occurs when all arguments have been acquired.  </p><blockquote>And so, applicatives enable automatic parallelisation of effectful computations.  No need to manually write code to do threaded coordination.</blockquote><p>Here&apos;s a simple example.  Let&apos;s first get three asynchronous IO operations:</p><pre><code class="language-csharp">var io1 = liftIO(() =&gt; File.ReadAllTextAsync(path1));
var io2 = liftIO(() =&gt; File.ReadAllTextAsync(path2));
var io3 = liftIO(() =&gt; File.ReadAllTextAsync(path3));
</code></pre><p>And some function that wants to use the result of those operations:</p><pre><code class="language-csharp">var concat = (string txt1, string txt2, string txt3) =&gt;
                   txt1 + txt2 + txt3;
</code></pre><p>Next we map and apply the IO computations.  These three IO operations will now all run in parallel and collect their results before invoking the <code>concat</code> function.</p><pre><code class="language-csharp">IO&lt;string&gt; res = concat.Map(io1).Apply(io2).Apply(io3);</code></pre><blockquote>You might be thinking &quot;but, you didn&apos;t curry the <code>concat</code> function first!&quot;.  You&apos;re right, because language-ext has <code>Map</code> and <code>Apply</code> overrides that will deal with that automatically for multi-argument delegates.  The overrides simply curry the function for you before invoking the regular <code>Map</code> and <code>Apply</code> methods.</blockquote><p>Another thing to note with the above expression is that <code>Map</code> is called on the function &#x2013; and so it doesn&apos;t get forked; only <code>io1</code>, <code>io2</code>, and <code>io3</code> get forked.  That means we&apos;re not launching pointless parallel processes to acquire the function (which would normally be available already).  </p><blockquote>Note the real-world <code>Apply</code> implementation for <code>IO</code> is <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Effects/IO/DSL/IOApply.cs?ref=paullouth.com">quite a bit more complex</a> because of how <code>IO&lt;A&gt;</code> has been implemented as a DSL and the optimisations put in place to avoid <code>async</code> when it&apos;s not needed.  It doesn&apos;t use <code>Fork</code> and instead unpacks <code>Task</code> values and uses <code>Task.WhenAll</code>.  The theory is the same though. IO concurrency happens automatically with the applicative <code>Apply</code> behaviour.</blockquote><p>Applicatives are a little hard to get your head around at first &#x2013; but they are incredibly powerful.  Even if you don&apos;t need the more &apos;hierarchal&apos; behaviour (as opposed to the sequential behaviour of monads) they can &#x2013; in the right circumstance &#x2013; be very concise and elegant.  However, in  C# it isn&apos;t always the case, so it&apos;s best to pick your battles and use them when you need their unique capabilities or when the resulting code <em>will </em>be more elegant.</p><p>This article is a little long now &#x2013; I still haven&apos;t explained the <code>Pure</code> method in <code>Applicative</code> and I wanted to cover how applicatives can be used for validation &#x2013; but I think I&apos;ll dedicate a separate article to that so I can give some more real-world examples.</p><p><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-5-validation/"><em>Part 5 &#x2013; Validation</em> </a></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 3 - foldables]]]></title><description><![CDATA[Foldables abstract the idea of aggregation away from simple lists (like Aggregate in LINQ) to many other types.  ]]></description><link>https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/</link><guid isPermaLink="false">65dfffd82ac0342e8bc93168</guid><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Sat, 02 Mar 2024 11:42:12 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/02/louth-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/02/louth-1.png" alt="Higher Kinds in C# with language-ext [Part 3 - foldables]"><p>This is a multi-part series of articles, it&apos;s worth going back to the earlier parts if you haven&apos;t read them already:</p><ul><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">Part 1 - Introduction, traits, semigroups, and monoids</a></li><li><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">Part 2 - Functors</a></li></ul><blockquote><em>And &quot;yes&quot;, this time the artwork is my own.  And whilst I&apos;m no Kandinsky, he&apos;s not as good at functional-programming as me, so I guess we&apos;re even!</em></blockquote><p>In part two we showed that by defining a separate trait-implementation type we could make a data-type (like <code>List&lt;A&gt;</code> and <code>Maybe&lt;A&gt;</code>) into a functor.  Functors require higher-rank polymorphism to work, and we made it work.  Yay!</p><p>Let&apos;s just do one more <code>Functor</code> type: <code>Either&lt;L, R&gt;</code>.  <code>Either&lt;L, R&gt;</code> is a little more interesting, because it has two generic-parameters, whereas <code>List&lt;A&gt;</code> and <code>Maybe&lt;A&gt;</code> have only one.  </p><pre><code class="language-csharp">// Data-types
public abstract record Either&lt;L, R&gt; : K&lt;Either&lt;L&gt;, R&gt;;
public record Left&lt;L, R&gt;(L Value) : Either&lt;L, R&gt;;
public record Right&lt;L, R&gt;(R Value) : Either&lt;L, R&gt;;

// Trait implementation
public class Either&lt;L&gt; : Functor&lt;Either&lt;L&gt;&gt;
{
    public static K&lt;Either&lt;L&gt;, B&gt; Map&lt;A, B&gt;(K&lt;Either&lt;L&gt;, A&gt; either, Func&lt;A, B&gt; f) =&gt;
        either switch
        {
            Left&lt;L, A&gt; (var l) =&gt; new Left&lt;L, B&gt;(l),
            Right&lt;L, A&gt; (var r) =&gt; new Right&lt;L, B&gt;(f(r))
        };
}

// Extensions that provides the down-casting
public static class EitherExtensions
{
    public static Either&lt;L, R&gt; As&lt;L, R&gt;(this K&lt;Either&lt;L&gt;, R&gt; ma) =&gt;
        (Either&lt;L, R&gt;)ma;
}
</code></pre><p>It should be relatively clear now that the trait-implementation should just have the <em>last </em>generic parameter removed.  So, <code>Either&lt;L, R&gt;</code> becomes <code>Either&lt;L&gt;</code>, <code>Maybe&lt;A&gt;</code> becomes <code>Maybe</code>, etc.</p><p>If you think about it, this is a little bit like how <a href="https://en.wikipedia.org/wiki/Partial_application?ref=paullouth.com">partial-application</a> works with functions.  But, because C# won&apos;t allow us to partially apply <code>Either&lt;L, R&gt;</code> by just providing the <code>L</code> &#x2013; we need a second type that is partially-applied.  That second type completes its application, not by getting all of its arguments from the type, but by moving the final argument <em>from</em> the type-signature <em>to</em> the method-signatures.  </p><blockquote>The <em>methods</em> within the partially-applied trait-implementation provide the final argument. <strong> <em>This is the key to the technique.</em></strong></blockquote><p>Let&apos;s look at another higher-kind now: <code>Foldable</code>.  Foldables are <em>aggregators.  </em>There are usually two methods: <code>Fold</code> and <code>FoldBack</code> &#x2013; sometimes called <code>FoldRight</code> and <code>FoldLeft</code>, but in language-ext we use the <code>Fold</code> and <code>FoldBack</code> parlance.  </p><p>For, the uninitiated, <code>Fold</code> is the same as <code>Aggregate</code> in LINQ (first item to last item aggregation); <code>FoldBack</code> is like doing the aggregation in reverse: last item to first.  </p><p>When you consider this generally: folding applies a binary-operator over the values within the structure. For example, <code>Fold</code> looks like this:</p><pre><code class="language-csharp">((((a * s) * b) * c) * ...)
</code></pre><p>And <code>FoldBack</code> is this:</p><pre><code class="language-csharp">(a * (b * (... * (z * s))))</code></pre><blockquote>The <code>*</code> operator is a placeholder operator for the <code>f</code> binary-function passed to <code>Fold</code> and <code>FoldBack</code>.  <code>a</code>, <code>b</code>, <code>c</code>, and <code>z</code> represent values in the foldable-structure and <code>s</code> represents an intial-state.  So, the operation gets &apos;seeded&apos; with <code>s</code> and depending on the precedence applied with the binary-operator we get <code>Fold</code> and <code>FoldBack</code>.</blockquote><p>The trait looks like this:</p><pre><code class="language-csharp">public interface Foldable&lt;T&gt; 
    where T : Foldable&lt;T&gt;
{
   public static abstract S Fold&lt;A, S&gt;(K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f);

   public static abstract S FoldBack&lt;A, S&gt;(K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f);
}   
    </code></pre><p>And, just like <code>Select</code> before, we can add our one-and-only implementation of the <code>Fold</code> and <code>FoldBack</code> extension methods:</p><pre><code class="language-csharp">public static class FoldableExtensions
{
    public static S Fold&lt;T, A, S&gt;(this K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.Fold(ta, initial, f);

    public static S FoldBack&lt;T, A, S&gt;(this K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.FoldBack(ta, initial, f);
}
</code></pre><p>Now we can get the three trait types we&apos;ve made so far <code>List</code>, <code>Maybe</code>, and <code>Either&lt;L&gt;</code> and make them foldable...</p><p><strong><em>List</em></strong></p><pre><code class="language-csharp">public record List : 
    Functor&lt;List&gt;,
    Foldable&lt;List&gt;
{
    public static K&lt;List, B&gt; Map&lt;A, B&gt;(K&lt;List, A&gt; xs, Func&lt;A, B&gt; f) =&gt;
        new List&lt;B&gt;(xs.As().Items.Select(f).ToArray());

    public static S Fold&lt;A, S&gt;(K&lt;List, A&gt; xs, S initial, Func&lt;S, A, S&gt; f) =&gt;
        xs.As().Items.Aggregate(initial, f);

    public static S FoldBack&lt;A, S&gt;(K&lt;List, A&gt; xs, S initial, Func&lt;S, A, S&gt; f) =&gt;
        xs.As().Items.AsEnumerable().Reverse().Aggregate(initial, f);
}
</code></pre><p><strong><em>Maybe</em></strong></p><pre><code class="language-csharp">
public class Maybe : 
    Functor&lt;Maybe&gt;,
    Foldable&lt;Maybe&gt;
{
    public static K&lt;Maybe, B&gt; Map&lt;A, B&gt;(K&lt;Maybe, A&gt; ma, Func&lt;A, B&gt; f) =&gt;
        ma switch
        {
            Just&lt;A&gt; (var x) =&gt; new Just&lt;B&gt;(f(x)),
            Nothing&lt;A&gt;      =&gt; new Nothing&lt;B&gt;()
        };

    public static S Fold&lt;A, S&gt;(K&lt;Maybe, A&gt; ma, S initial, Func&lt;S, A, S&gt; f) =&gt;
        ma switch
        {
            Just&lt;A&gt; (var x) =&gt; f(initial, x),
            Nothing&lt;A&gt;      =&gt; initial
        };

    public static S FoldBack&lt;A, S&gt;(K&lt;Maybe, A&gt; ma, S initial, Func&lt;S, A, S&gt; f) =&gt;
        Fold(ma, initial, f);
}
</code></pre><p><strong><em>Either&lt;L&gt;</em></strong></p><pre><code class="language-csharp">
public class Either&lt;L&gt; : 
    Functor&lt;Either&lt;L&gt;&gt;,
    Foldable&lt;Either&lt;L&gt;&gt;
{
    public static K&lt;Either&lt;L&gt;, B&gt; Map&lt;A, B&gt;(K&lt;Either&lt;L&gt;, A&gt; ma, Func&lt;A, B&gt; f) =&gt;
        ma switch
        {
            Left&lt;L, A&gt; (var l)  =&gt; new Left&lt;L, B&gt;(l),
            Right&lt;L, A&gt; (var r) =&gt; new Right&lt;L, B&gt;(f(r))
        };

    public static S Fold&lt;A, S&gt;(K&lt;Either&lt;L&gt;, A&gt; ma, S initial, Func&lt;S, A, S&gt; f) =&gt;
        ma switch
        {
            Left&lt;L, A&gt;          =&gt; initial,
            Right&lt;L, A&gt; (var r) =&gt; f(initial, r),
        };

    public static S FoldBack&lt;A, S&gt;(K&lt;Either&lt;L&gt;, A&gt; ma, S initial, Func&lt;S, A, S&gt; f) =&gt;
        Fold(ma, initial, f);
}
</code></pre><blockquote>We still haven&apos;t modified the <code>List&lt;A&gt;</code>, <code>Maybe&lt;A&gt;</code>, or <code>Either&lt;L, R&gt;</code> types directly.  We&apos;re just extending the set of capabilities via the trait-implementations.</blockquote><p>When we made our types into functors, they gained the ability to <code>Map</code>, but nothing else really.  So, it was a fair amount of typing to apparently not get much in return.  <code>Foldable</code> is quite different.  Let&apos;s see what we can give <em>any </em>type that implements <code>Foldable</code>.</p><p>First up, let&apos;s count the items in <em>any </em>foldable:</p><pre><code class="language-csharp">public static int Count&lt;T, A&gt;(this K&lt;T, A&gt; ta)
    where T : Foldable&lt;T&gt; =&gt;
    ta.Fold(0, (s, _) =&gt; s + 1);</code></pre><p>And test it:</p><pre><code class="language-csharp">var mx = new Nothing&lt;int&gt;();
var my = new Just&lt;int&gt;(100);
var mz = new List&lt;int&gt;([1, 2, 3, 4, 5]);

var c1 = mx.Count();    // 0 
var c2 = my.Count();    // 1
var c3 = mz.Count();    // 5
</code></pre><p>So we just gave <strong><em>all foldables </em></strong>some additional (useful) functionality without touching the original types or traits.  These can be used in any generic function that works with foldables.  </p><p>Can we do more?</p><p>Let&apos;s sum the items in <em>any </em>foldable, with <em>any </em>numeric bound-value:</p><pre><code class="language-csharp">public static A Sum&lt;T, A&gt;(this K&lt;T, A&gt; ta)
    where T : Foldable&lt;T&gt; 
    where A : INumber&lt;A&gt; =&gt;
    ta.Fold(A.Zero, (s, x) =&gt; s + x);</code></pre><p>And test it:</p><pre><code class="language-csharp">var mx = new Nothing&lt;int&gt;();
var my = new Just&lt;int&gt;(100);
var mz = new List&lt;int&gt;([1, 2, 3, 4, 5]);

var c1 = mx.Sum();    // 0 
var c2 = my.Sum();    // 100
var c3 = mz.Sum();    // 15
</code></pre><p>We could also see if <em>any</em> foldable is empty:</p><pre><code class="language-csharp">public static bool IsEmpty&lt;T, A&gt;(this K&lt;T, A&gt; ta)
    where T : Foldable&lt;T&gt; =&gt;
    ta.Fold(true, (_, _) =&gt; false);
</code></pre><p>If the bound-value type is monoidal then we can use that to aggregate using the monoid&apos;s associative operator:</p><pre><code class="language-csharp">public static A Fold&lt;T, A&gt;(this K&lt;T, A&gt; ta)
    where T : Foldable&lt;T&gt;
    where A : Monoid&lt;A&gt; =&gt;
    ta.Fold(A.Empty, (s, x) =&gt; s + x);
</code></pre><p>We can convert <em>any</em> foldable into an <code>IEnumerable</code>:</p><pre><code class="language-csharp">public static IEnumerable&lt;A&gt; AsEnumerable&lt;T, A&gt;(this K&lt;T, A&gt; ta)
    where T : Foldable&lt;T&gt;
{
    var list = new System.Collections.Generic.List&lt;A&gt;();
    return ta.Fold(list, (s, x) =&gt;
    {
        s.Add(x);
        return s;
    });
}</code></pre><p>We can implement more of the standard LINQ operators (without &apos;magic methods&apos;):</p><pre><code class="language-csharp">// Returns true if the predicate holds for all items
public static bool All&lt;T, A&gt;(this K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f)
    where T : Foldable&lt;T&gt; =&gt;
    ta.Fold(true, (s, x) =&gt; s &amp;&amp; f(x));

// Returns true if the predicate holds for any item
public static bool Any&lt;T, A&gt;(this K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f)
    where T : Foldable&lt;T&gt; =&gt;
    ta.Fold(false, (s, x) =&gt; s || f(x));</code></pre><p>And we can check if a known item is within <em>any</em> foldable structure:</p><pre><code class="language-csharp">public static bool Contains&lt;T, A&gt;(this K&lt;T, A&gt; ta, A value)
    where A : IEquatable&lt;A&gt;
    where T : Foldable&lt;T&gt; =&gt;
    ta.Any(x =&gt; x.Equals(value));
</code></pre><blockquote>These functions are written just once.  And they work for <code>List&lt;A&gt;</code>, <code>Maybe&lt;A&gt;</code>, and <code>Either&lt;L, R&gt;</code> automatically.  They will also work for any foldable <strong><em>you</em></strong> write!  Yay, free code!</blockquote><p>Now, some of the more performance minded individuals reading this might think &quot;Er, but these methods do more work than they need to&quot;.   And, you&apos;d be right.  For example, the <code>IsEmpty</code> method has to traverse every item in the foldable, even though we would know <em>on the first item</em> if it&apos;s empty or not.  <code>Count</code> traverses every item also, yet <code>List&lt;A&gt;</code> has an internal representation that is an array &#x2013; it knows how many items there are without walking the collection.</p><p>We fix this by moving these methods <em>into</em> <code>Foldable</code> and making them default implementations that can be overridden where desired. </p><p><strong><em>New <code>Foldable&lt;T&gt;</code> trait:</em></strong></p><pre><code class="language-csharp">public interface Foldable&lt;T&gt; 
    where T : Foldable&lt;T&gt;
{
    // Abstract members that everyone has to implement

    public static abstract S Fold&lt;A, S&gt;(K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f);

    public static abstract S FoldBack&lt;A, S&gt;(K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f);
    
    // Virtual members with useful default implementations

    public static virtual bool IsEmpty&lt;A&gt;(K&lt;T, A&gt; ta) =&gt;
        T.Fold(ta, true, (_, _) =&gt; false);

    public static virtual int Count&lt;A&gt;(K&lt;T, A&gt; ta) =&gt;
        T.Fold(ta, 0, (s, _) =&gt; s + 1);

    public static virtual A Sum&lt;A&gt;(K&lt;T, A&gt; ta)
        where A : INumber&lt;A&gt; =&gt;
        T.Fold(ta, A.Zero, (s, x) =&gt; s + x);

    public static virtual A Fold&lt;A&gt;(K&lt;T, A&gt; ta)
        where A : Monoid&lt;A&gt; =&gt;
        T.Fold(ta, A.Empty, (s, x) =&gt; s + x);

    public static virtual IEnumerable&lt;A&gt; AsEnumerable&lt;A&gt;(K&lt;T, A&gt; ta)
    {
        var list = new System.Collections.Generic.List&lt;A&gt;();
        return ta.Fold(list, (s, x) =&gt;
        {
            s.Add(x);
            return s;
        });
    }

    public static virtual bool All&lt;A&gt;(K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f) =&gt;
        T.Fold(ta, true, (s, x) =&gt; s &amp;&amp; f(x));

    public static virtual bool Any&lt;A&gt;(K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f) =&gt;
        T.Fold(ta, false, (s, x) =&gt; s || f(x));

    public static virtual bool Contains&lt;A&gt;(K&lt;T, A&gt; ta, A value)
        where A : IEquatable&lt;A&gt; =&gt;
        T.Any(ta, x =&gt; x.Equals(value));    
}</code></pre><p>Note, how the methods we&apos;ve moved into <code>Foldable</code> are <code>static virtual</code> &#x2013; which means we can override them in our trait-implementations.  But, if we don&apos;t, we still get the free functionality.  The default implementations happen to be pretty optimial for <code>Maybe</code> and <code>Either</code> &#x2013; they could be better, but&apos;s probably not worth the effort to provide hand-written overrides; but for <code>List</code> we should definitely do some manual overrides if we want to get the best performance.</p><p><strong><em>Updated <code>List</code> trait-implementation with optimised overrides:</em></strong></p><pre><code class="language-csharp">public record List : 
    Functor&lt;List&gt;,
    Foldable&lt;List&gt;
{
    public static K&lt;List, B&gt; Map&lt;A, B&gt;(K&lt;List, A&gt; xs, Func&lt;A, B&gt; f)
    {
        // Optimises by pre-allocating the array before mapping
        var items = xs.As().Items;
        var bs = new B[items.Length];
        var ix = 0;
        foreach(var item in items)
        {
            bs[ix] = f(item);
            ix++;
        }
        return new List&lt;B&gt;(bs);
    }

    public static S Fold&lt;A, S&gt;(K&lt;List, A&gt; xs, S state, Func&lt;S, A, S&gt; f)
    {
        // Optimises by running as a simple imperative for-loop
        foreach(var item in xs.As().Items)
        {
            state = f(state, item);
        }
        return state;
    }

    public static S FoldBack&lt;A, S&gt;(K&lt;List, A&gt; xs, S state, Func&lt;S, A, S&gt; f)
    {
        // Optimises by running an imperative for-loop backwards 
        var items = xs.As().Items;
        for (var ix = items.Length - 1; ix &gt;= 0; ix--)
        {
            state = f(state, items[ix]);
        }
        return state;
    }

    public static bool IsEmpty&lt;A&gt;(K&lt;List, A&gt; ta) =&gt;
        // Optimises by using the known length of the array 
        ta.As().Items.Length == 0;

    public static int Count&lt;A&gt;(K&lt;List, A&gt; ta) =&gt;
        // Optimises by using the known length of the array 
        ta.As().Items.Length;

    public static IEnumerable&lt;A&gt; AsEnumerable&lt;A&gt;(K&lt;List, A&gt; ta) =&gt;
        // Optimises by passing the array back directly 
        ta.As().Items;

    public static bool All&lt;A&gt;(K&lt;List, A&gt; ta, Func&lt;A, bool&gt; f)
    {
        // Optimises by turning into a simple loop that can bail out early
        foreach (var item in ta.As().Items)
        {
            if (!f(item)) return false;
        }
        return true;
    }

    public static bool Any&lt;A&gt;(K&lt;List, A&gt; ta, Func&lt;A, bool&gt; f)
    {
        // Optimises by turning into a simple loop that can bail out early
        foreach (var item in ta.As().Items)
        {
            if (f(item)) return true;
        }
        return false;
    }
}
</code></pre><blockquote>What&apos;s really nice about this is that we can &apos;get moving&apos; and write our code to leverage these higher-kinded types and gain all of this functionality and then come back later to provide more optimal solutions.  <em>The definition of not optimising prematurely.</em></blockquote><p>We should update the extension methods to use these new trait methods too.  Here&apos;s the full set of extensions so far:</p><pre><code class="language-csharp">public static class FoldableExtensions
{
    public static K&lt;F, B&gt; Select&lt;F, A, B&gt;(this K&lt;F, A&gt; fa, Func&lt;A, B&gt; f)
        where F : Functor&lt;F&gt; =&gt;
        F.Map(fa, f);
    
    public static K&lt;F, B&gt; Map&lt;F, A, B&gt;(this K&lt;F, A&gt; fa, Func&lt;A, B&gt; f)
        where F : Functor&lt;F&gt; =&gt;
        F.Map(fa, f);

    public static S Fold&lt;T, A, S&gt;(this K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.Fold(ta, initial, f);

    public static S FoldBack&lt;T, A, S&gt;(this K&lt;T, A&gt; ta, S initial, Func&lt;S, A, S&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.Fold(ta, initial, f);

    public static bool IsEmpty&lt;T, A&gt;(this K&lt;T, A&gt; ta)
        where T : Foldable&lt;T&gt; =&gt;
        T.IsEmpty(ta);

    public static int Count&lt;T, A&gt;(this K&lt;T, A&gt; ta)
        where T : Foldable&lt;T&gt; =&gt;
        T.Count(ta);

    public static A Sum&lt;T, A&gt;(this K&lt;T, A&gt; ta)
        where T : Foldable&lt;T&gt; 
        where A : INumber&lt;A&gt; =&gt;
        T.Sum(ta);

    public static A Fold&lt;T, A&gt;(this K&lt;T, A&gt; ta)
        where T : Foldable&lt;T&gt;
        where A : Monoid&lt;A&gt; =&gt;
        T.Fold(ta);

    public static IEnumerable&lt;A&gt; AsEnumerable&lt;T, A&gt;(this K&lt;T, A&gt; ta)
        where T : Foldable&lt;T&gt; =&gt;
        T.AsEnumerable(ta);

    public static bool All&lt;T, A&gt;(this K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.All(ta, f);

    public static bool Any&lt;T, A&gt;(this K&lt;T, A&gt; ta, Func&lt;A, bool&gt; f)
        where T : Foldable&lt;T&gt; =&gt;
        T.Any(ta, f);

    public static bool Contains&lt;T, A&gt;(this K&lt;T, A&gt; ta, A value)
        where A : IEquatable&lt;A&gt;
        where T : Foldable&lt;T&gt; =&gt;
        T.Contains(ta, value);
}</code></pre><p>It is clear from this approach that we don&apos;t have to forego performance to leverage more abstract compositional capabilities.  These methods will be as fast as any handwritten code and yet we can write abstract functions that work with <em>any</em> foldables and <em>any </em>functors; yet when they&apos;re consumed they run the highly optimised trait implementations, not some generic code that has no understanding of the underlying type.  </p><p>Contrast that with <code>IEnumerable&lt;T&gt;</code>, which, once your collection-type has been cast to from its concrete type, like <code>List&lt;T&gt;</code>, to its abstract representation of <code>IEnumerable&lt;T&gt;</code>, instantly becomes opaque &#x2013; with the only access to the underlying type being its ability to yield an enumerator.  Yet, we have a ton of extension methods hanging off the type that are completely clueless to what&apos;s underneath.  There are no such issues with the higher-kinds + traits approach!</p><p></p><figure class="kg-card kg-image-card"><a href="https://wiki.haskell.org/Typeclassopedia?ref=paullouth.com"><img src="https://paullouth.com/content/images/2024/02/Typeclassopedia-diagram.png" class="kg-image" alt="Higher Kinds in C# with language-ext [Part 3 - foldables]" loading="lazy" width="753" height="260" srcset="https://paullouth.com/content/images/size/w600/2024/02/Typeclassopedia-diagram.png 600w, https://paullouth.com/content/images/2024/02/Typeclassopedia-diagram.png 753w" sizes="(min-width: 720px) 720px"></a></figure><p>On the Haskell wiki is what&apos;s known as the &apos;<a href="https://wiki.haskell.org/Typeclassopedia?ref=paullouth.com">Typeclassopedia</a>&apos;.  So far, we&apos;ve covered:</p><ul><li><code>Semigroup</code></li><li><code>Monoid</code></li><li><code>Foldable</code></li><li><code>Functor</code></li><li>and mentioned in passing: <code>Applicative</code> and <code>Traversable</code></li></ul><p>Can you guess where we&apos;re going next?</p><p><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-4-applicatives/"><em>Part 4</em></a><em> </em></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 2 - functors]]]></title><description><![CDATA[We introduce functors - one of the most powerful concepts in category theory - but in code form allows for the mapping of values within a structure.  ]]></description><link>https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/</link><guid isPermaLink="false">65ddc31899e5fbe500fe8d45</guid><category><![CDATA[functor]]></category><category><![CDATA[hkt]]></category><category><![CDATA[traits]]></category><category><![CDATA[language-ext]]></category><category><![CDATA[csharp]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Thu, 29 Feb 2024 11:27:10 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/02/pjimage-11.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/02/pjimage-11.png" alt="Higher Kinds in C# with language-ext [Part 2 - functors]"><p>In <a href="https://paullouth.com/higher-kinds-in-c-with-language-ext/">part 1</a> of this series I introduced the type <code>K&lt;F, A&gt;</code> and left you all hanging with the promise that it would bring higher-kinded traits to C#.  So, let&apos;s dig in a little to see how it works.</p><p>Firstly, you&apos;ll recall (from part 1) that we couldn&apos;t implement <code>Mappable</code> &#x2013; using the traits technique &#x2013; because it baked-in the <em>bound-value type:</em> <code>A</code> and didn&apos;t allow us to map to a new <em>bound-value type </em>of <code>B</code>.</p><p>So, it should be clear that a type like <code>List&lt;A&gt;</code> can&apos;t ever inherit a trait that <em>bakes in</em> the <code>A</code>. If we want to implement an generic version of <code>Select</code> we need a <code>Mappable</code> trait that has no <code>A</code>.  </p><p>Let&apos;s try that:</p><pre><code class="language-csharp">public interface Mappable&lt;F&gt; 
    where F : Mappable&lt;F&gt;
{
    public static abstract F&lt;B&gt; Select&lt;A, B&gt;(F&lt;A&gt; list, Func&lt;A, B&gt; f);
}</code></pre><p>But, we already know we can&apos;t use: <code>F&lt;A&gt;</code> and <code>F&lt;B&gt;</code> &#x2013; where <code>F</code> would be <code>List</code> and <code>A</code> and <code>B</code> would be the bound-value type of the items in the list.  Why? Because C# doesn&apos;t support higher kinds!</p><p>What we can do though is use the new language-ext type: <code>K&lt;F, A&gt;</code> revealed in the last article:</p><pre><code class="language-csharp">public interface Mappable&lt;F&gt;
    where F : Mappable&lt;F&gt;
{
    public static abstract K&lt;F, B&gt; Select&lt;A, B&gt;(K&lt;F, A&gt; list, Func&lt;A, B&gt; f);
}</code></pre><p>This allows us to use <code>F</code> as an &apos;anchor&apos; for an <em>another</em> type that will help us understand something about the structure of the &apos;<em>mappable</em> <em>thing&apos;.</em></p><blockquote><em>If you haven&apos;t worked it out yet &#x2013; <code>K</code> is short for <code>Kind</code>.  I wanted to keep the type concise because it&apos;s needed a lot and I want the focus to be on the generic parameters, not the type-name.  You&apos;ll see why this is important when we start filling in the generic parameters with concrete types.</em></blockquote><p>First, let&apos;s create a simple list type:</p><pre><code class="language-csharp">public record List&lt;A&gt;(A[] Items) : K&lt;List, A&gt;;
</code></pre><p>Notice, how it inherits: <code>K&lt;List, A&gt;</code> &#x2013; but we don&apos;t have a type called <code>List</code>, just <code>List&lt;A&gt;</code>.  <code>List</code> is the type that will implement the <code>Mappable&lt;F&gt;</code> trait &#x2013; let&apos;s start to make it:</p><pre><code class="language-csharp">public class List : Mappable&lt;List&gt;
{
    public static K&lt;List, B&gt; Select&lt;A, B&gt;(K&lt;List, A&gt; list, Func&lt;A, B&gt; f)
    {
        throw new NotImplementedException();
    }
}
</code></pre><p>OK, that&apos;s looking very interesting!  We have a <code>K&lt;List, A&gt;</code> that maps to a <code>K&lt;List, B&gt;</code>.  If you look back at the implementation of <code>List&lt;A&gt;</code> you&apos;ll see that it inherits a <code>K&lt;List, A&gt;</code> &#x2013; so we can downcast a <code>K&lt;List, A&gt;</code> knowing it&apos;s a <code>List&lt;A&gt;</code>:</p><pre><code class="language-csharp">public class List : Mappable&lt;List&gt;
{
    public static K&lt;List, B&gt; Select&lt;A, B&gt;(K&lt;List, A&gt; list, Func&lt;A, B&gt; f) =&gt;
        new List&lt;B&gt;(((List&lt;A&gt;)list)
                        .Items
                        .Select(f)
                        .ToArray());
}
</code></pre><p>And that works!  We have a general case <code>Mappable</code> implementation for <code>List&lt;A&gt;</code>.  </p><p>The casting is a little ugly though, so let&apos;s add a simple extension method to do the downcast:</p><pre><code class="language-csharp">public static class ListExtensions
{
    public static List&lt;A&gt; As&lt;A&gt;(this K&lt;List, A&gt; ma) =&gt;
        (List&lt;A&gt;)ma;
}
</code></pre><p>Now, we can remove the cast from the implementation:</p><pre><code class="language-csharp">public class List : Mappable&lt;List&gt;
{
    public static K&lt;List, B&gt; Select&lt;A, B&gt;(K&lt;List, A&gt; list, Func&lt;A, B&gt; f) =&gt;
        new List&lt;B&gt;(list.As().Items.Select(f).ToArray());
}</code></pre><p>And everything starts to look really elegant.</p><blockquote>Seasoned developers might wince at the down-casting, but we should only ever derive one type from <code>K&lt;List, A&gt;</code> &#x2013; so it <em>must</em> be a <code>List&lt;A&gt;</code>.  Obviously, if you did something silly and derived two types from <code>K&lt;List, A&gt;</code> then you&apos;d get a failure on first usage, so it&apos;s not really a systemic risk to your code if you make a mistake.  I&apos;m OK with this.</blockquote><p>We can then take that further, by creating the &#x2013; <em>one and only &#x2013; </em><code>Select</code> extension method.  Yes, you only need to write this extension once!  </p><pre><code class="language-csharp">public static class MappableExtensions
{
    public static K&lt;F, B&gt; Select&lt;F, A, B&gt;(this K&lt;F, A&gt; fa, Func&lt;A, B&gt; f)
        where F : Mappable&lt;F&gt; =&gt;
        F.Select(fa, f);
}</code></pre><p>And, that&apos;s it &#x2013; the extension method to end all extension methods.  We can now use that like any other LINQ extension.  And it will work for all types that implement <code>Mappable</code>:</p><pre><code class="language-csharp">var list = new List&lt;int&gt;([1, 2, 3]);

var nlist = list.Select(x =&gt; x + 1)
                .Select(x =&gt; x * 2);
</code></pre><p>As long as your data-type inherits <code>K&lt;F, A&gt;</code> and you have a sibling type that implements <code>Mappable&lt;F&gt;</code> then you will automatically gain the <code>Select</code> LINQ operator.</p><blockquote><code>K&lt;F, A&gt;</code> creates the hook to a higher-kinded trait type: <code>F</code> that allows us to parameterise with any type we want in place of <code>A</code>.</blockquote><p>Now the downside.  In the last example, <code>Select</code> returns a <code>K&lt;List, int&gt;</code> - not a <code>List&lt;int&gt;</code>.  So, whilst we&apos;re able to chain many <code>Select</code> calls together, we can&apos;t assign the result directly to <code>List&lt;int&gt;</code>.  But, we can use our downcast method to do that!</p><pre><code class="language-csharp">List&lt;int&gt; nlist = list.Select(x =&gt; x + 1)
                      .Select(x =&gt; x * 2)
                      .As();
</code></pre><p>This isn&apos;t ideal, of course, but it has a tiny overhead &#x2013; it&apos;s just casting after all &#x2013; and it&apos;s not too intrusive.  The only way to avoid this is for the C# team to add higher-kinds proper (or allow implicit casting of interfaces &#x2013; that&apos;s another discussion!); but for now this works and gives us all of the same benefits.</p><blockquote>One thing I&apos;ve noticed, as I build out this capability in language-ext, is how little I am needing to call <code>.As()</code> &#x2013; because if you stay in the &apos;abstract state&apos; then you can continue to rely on the higher-kinded extensions to &apos;just work&apos;.  It&apos;s only when you need to go back to a concrete value that <code>.As()</code> is needed.</blockquote><p>Let&apos;s try implementing another <code>Mappable</code> type:</p><pre><code class="language-csharp">public abstract record Maybe&lt;A&gt; : K&lt;Maybe, A&gt;;
public record Just&lt;A&gt;(A Value) : Maybe&lt;A&gt;;
public record Nothing&lt;A&gt;() : Maybe&lt;A&gt;;</code></pre><p>Here we create a simple discriminated-union type called <code>Maybe&lt;A&gt;</code> that has two states: <code>Just</code> and <code>Nothing</code>.</p><blockquote>It&apos;s the same as <code>Option&lt;A&gt;</code> in language-ext, I just wanted to keep the example separate for now.  <code>Just</code> is <code>Some</code> and <code>Nothing</code> is <code>None</code>.</blockquote><p>Now, let&apos;s create the <em>trait-implementing</em> <code>Maybe</code> type:</p><pre><code class="language-csharp">public class Maybe : Mappable&lt;Maybe&gt;
{
    public static K&lt;Maybe, B&gt; Select&lt;A, B&gt;(K&lt;Maybe, A&gt; maybe, Func&lt;A, B&gt; f) =&gt;
        maybe switch
        {
            Just&lt;A&gt; (var x) =&gt; new Just&lt;B&gt;(f(x)),
            Nothing&lt;A&gt;      =&gt; new Nothing&lt;B&gt;()
        };
}
</code></pre><p>And add the downcast extension:</p><pre><code class="language-csharp">public static class MaybeExtensions
{
    public static Maybe&lt;A&gt; As&lt;A&gt;(this K&lt;Maybe, A&gt; ma) =&gt;
        (Maybe&lt;A&gt;)ma;
}</code></pre><p>Now we can leverage the &#x2013; already existing &#x2013; <code>Select</code> extension method:</p><pre><code class="language-csharp">var mx = new Just&lt;int&gt;(100);
var my = new Nothing&lt;int&gt;();

var r1 = mx.Select(x =&gt; x + 1)
           .Select(x =&gt; x * 3); // Just(303)

var r2 = my.Select(x =&gt; x + 1)
           .Select(x =&gt; x * 3); // Nothing
</code></pre><p>You may think &quot;So what? We could do this with extension methods and only have to write 1 method for each type.&quot; &#x2013; what we couldn&apos;t do is write generic functions that work with <em>any </em><code>Mappable</code> type; we&apos;d have to implement <code>Foo(Maybe&lt;string&gt; mx)</code>, <code>Foo(List&lt;string&gt; mx)</code>, etc. </p><p>Now we can write those functions once:</p><pre><code class="language-csharp">public static K&lt;F, int&gt; Foo&lt;F&gt;(K&lt;F, string&gt; ma) 
    where F : Mappable&lt;F&gt; =&gt;
    ma.Select(x =&gt; x.Length);
</code></pre><p>Those of you that have been paying attention will notice that <code>Mappable&lt;F&gt;</code> is, of course, a <code>Functor&lt;F&gt;</code>!  Yes, I realise this was hardly the reveal of the century, but for those of you who are relatively new to functional programming, terms like <code>Functor</code> might be a bit too much to take in whilst learning about a new technique for higher kinds! Now when you hear &quot;Functor&quot; just think &quot;Mappable&quot;.</p><p>Anyway, <code>Mappable</code> is <code>Functor</code> and <code>Select</code> should be called <code>Map</code>.  Let&apos;s do that:</p><pre><code class="language-csharp">public interface Functor&lt;F&gt; 
    where F : Functor&lt;F&gt;
{
    public static abstract K&lt;F, B&gt; Map&lt;A, B&gt;(K&lt;F, A&gt; fa, Func&lt;A, B&gt; f);
}
</code></pre><p>If we put our definition of <code>Functor</code> side-by-side with the <a href="https://hackage.haskell.org/package/base-4.19.1.0/docs/src/GHC.Base.html?ref=paullouth.com#Functor">Haskell definition of <code>Functor</code></a> &#x2013; because Haskell is a language that has higher-kinds, traits, and probably has done more to promote this style of abstract programming than any other language...</p><pre><code class="language-haskell">class Functor f where
  fmap :: (a -&gt; b) -&gt; f a -&gt; f b</code></pre><p>You might notice a striking similarity!  </p><ul><li><code>Functor f == Functor&lt;F&gt;</code> </li><li><code>f a == K&lt;F, A&gt;</code> </li><li><code>f b == K&lt;F, B&gt;</code> </li><li><code>(a -&gt; b) == Func&lt;A, B&gt;</code> </li></ul><p>They&apos;re not just strikingly similar &#x2013;  but, barring the order of the arguments, they&apos;re exactly the same! </p><blockquote>In the <a href="https://github.com/louthy/language-ext/blob/main/LanguageExt.Core/Traits/Functor/Functor.Trait.cs?ref=paullouth.com" rel="noreferrer">final version in language-ext</a>, even the order of the arguments is the same.  I will go into the reasons for that in a later article.</blockquote><p>OK, so it&apos;s worth stopping to reflect right now &#x2013; is this really higher-rank polymorphism?  My answer to that is &quot;100% yes!&quot;.  Are there some compromises?  Yeah, some, but they&apos;re pretty mild for what we gain.  It is true that this isn&apos;t using lambda-abstractions in the type-system, so it&apos;s not completely general like Haskell, but it does generalise correctly for traits, which is what matters the most.</p><p>It&apos;s also worth remembering that our original data-types haven&apos;t been modified at all.  </p><pre><code class="language-csharp">// List&lt;A&gt;
public record List&lt;A&gt;(A[] Items) : K&lt;List, A&gt;;

// Maybe&lt;A&gt;
public abstract record Maybe&lt;A&gt; : K&lt;Maybe, A&gt;;
public record Just&lt;A&gt;(A Value) : Maybe&lt;A&gt;;
public record Nothing&lt;A&gt;() : Maybe&lt;A&gt;;</code></pre><p>All of the <em>&apos;action&apos;</em> is in the trait implementation types: <code>List</code> and <code>Maybe</code>.  This is very similar to how class-instances work in Haskell (class instances are implementations of type-classes &#x2013; i.e. traits).  You create a data-type that represents the &apos;shape&apos; and the trait-implementations represent the &apos;capability&apos; &#x2013; this is a nice separation of concerns and leaves the data-type being a pure structure that can travel anywhere.  This simplifies parallel processing and serialisation/deserialisation. </p><p>The primary difference for us, in C#, is the need for the data-type to derive from <code>K&lt;F, A&gt;</code> &#x2013; this is unavoidable, brings some limitations, but still allows us to build very powerful generic code.  </p><p>One way to mentally process this (especially if you&apos;ve never spent time in a language with higher-kinds) is imagine C# <em>without</em> generics &#x2013; those of you who have been programming C# from <code>v1.0</code> won&apos;t find that very hard to imagine! &#x2013; could you imagine having a type-less <code>List</code> that only took <code>object</code>?  Could you imagine the code explosion as you need to write 100 functions (all doing basically the same thing) for different types?  Well, when you step up another rank with your generics, you gain a similar leap in power.</p><p>A perfect example is the <a href="https://github.com/louthy/language-ext/tree/186bf9fc7439d614f5901bb8dfa3a50179a069b9/LanguageExt.Core/Transformer/Traverse?ref=paullouth.com">implementations of <code>Traverse</code> and <code>Sequence</code> in language-ext <code>v4</code></a> &#x2013; I have written over 400 functions and over 1200 unit-tests by hand (actually, I got some help from the community &#x2013; thank you, community!) that all do the same thing, but with different types.  And guess what, <em>if <strong>you</strong> decide to write a type that should be traversable </em>&#x2013;  it won&apos;t work with any of the language-ext traversables or applicatives, you&apos;d have to write <code>n</code> variants of traverse yourself.  All because we can&apos;t write this type: <code>T&lt;F&lt;A&gt;&gt;</code> &#x2013; where the <code>T</code> is <code>Traversable</code> and <code>F</code> is an <code>Applicative</code>.  </p><p>In <code>v5</code> I can write: <code>K&lt;T, K&lt;F, A&gt;&gt;</code> which allows for a single implementation of <code>Traverse</code> per type written (i.e. you implement your <code>Traversable</code> trait, once, like with <code>Functor</code>).  And, <em>if <strong>you</strong> decide to write a traversable or applicative type,</em> it will automatically work with the traversable and applicative types in language-ext: you&apos;re not  just limited to what I can provide in the library any more.  True extensibility.</p><blockquote>But that&apos;s for a later, we need to build up to that!  I think that&apos;s enough for part 2.  It&apos;s worth trying to digest the implications of this approach before moving on.  Obviously <code>Functor</code> is a rather trivial type &#x2013;  so it may appear that we don&apos;t get a lot from this, but you&apos;ll quickly see how this technique gives us functional programming super powers! </blockquote><p><em>In </em><a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-3-foldables/"><em>Part 3</em></a><em> we look at foldables!</em></p>]]></content:encoded></item><item><title><![CDATA[Higher Kinds in C# with language-ext [Part 1]]]></title><description><![CDATA[Version 5 of language-ext introduces the concept of higher-kinded traits.  This series unpacks the implications of that!]]></description><link>https://paullouth.com/higher-kinds-in-c-with-language-ext/</link><guid isPermaLink="false">65dcce3b99e5fbe500fe8b03</guid><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Tue, 27 Feb 2024 10:01:53 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/02/sun.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/02/sun.png" alt="Higher Kinds in C# with language-ext [Part 1]"><p>Those who have been following the <a href="https://github.com/louthy/language-ext/?ref=paullouth.com">language-ext repo</a> will know that I am building up to a really massive version 5 release.  I am looking at the release notes that I have been trying to keep up to date as I go and they&apos;re already up to nearly 1000 lines of text.  And although there&apos;s quite a lot of content, there&apos;s also 100s of lines of just headings (waiting for the content)!  So, the final release notes are going to be huge and a lot to take in.</p><blockquote>Version 5 of language-ext is about as close to a rewrite as it&apos;s ever going to get.  So there&apos;s a lot to cover. </blockquote><p>Rather than have a big surprise on day 1 of the release, I figured I&apos;d keep language-ext in a <code>v5-beta</code> state for longer (it is stable now, so prefer it over <code>v4</code> if you&apos;re starting fresh) and in parallel I am starting this blog series to try and prepare the ground and whet the appetite somewhat.  I also want terrify you enough that you upgrade with caution! </p><blockquote>Note also that language-ext is getting more and more refinements to the ideas laid out in this series of articles and so apologies if some of the examples don&apos;t work as stated.  I will do my best to review this series at regular intervals to make sure it&apos;s up to date &#x2013; feel free to message me through the language-ext repo if you spot any issues.</blockquote><h2 id="traits">Traits</h2><p>A recent C# feature is <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members?ref=paullouth.com">static interface members</a> &#x2013; this opens up some new possibilities for bending C# to make <a href="https://en.wikipedia.org/wiki/Trait_(computer_programming)?ref=paullouth.com">trait</a> like functionality work.  You may have already seen the technique:</p><pre><code class="language-csharp">public interface Addable&lt;SELF&gt; where SELF : Addable&lt;SELF&gt;
{
    public static abstract SELF Add(SELF x, SELF y);
}
</code></pre><p>Note, how the <code>Add</code> member is <code>static abstract</code> and that the interface has a constraint that <code>SELF</code> is forced to inherit <code>Addable&lt;SELF&gt;</code>, meaning this trait can&apos;t stand alone (i.e. be ad-hoc like in other languages).</p><p>We can then create two distinct types that inherit the <code>Addable</code> trait:</p><pre><code class="language-csharp">public record MyList&lt;A&gt;(A[] values) : 
    Addable&lt;MyList&lt;A&gt;&gt;
{
    public static MyList&lt;A&gt; Add(MyList&lt;A&gt; x, MyList&lt;A&gt; y) =&gt; 
        new (x.values.Concat(y.values).ToArray());
}

public record MyString(string value) : 
    Addable&lt;MyString&gt;
{
    public static MyString Add(MyString x, MyString y) =&gt; 
        new (x.value + y.value);
}
</code></pre><p>They both inherit <code>Addable</code> and pass themselves as the argument to construct the concrete <code>Addable</code> implementation.</p><p>We can then create a function that adds anything &#x2013; as long a the type is <code>Addable</code>:</p><pre><code class="language-csharp">A AddAnything&lt;A&gt;(A x, A y) where A : Addable&lt;A&gt; =&gt;
    A.Add(x, y);
</code></pre><p>And now we can call <code>AddAnything</code> with either one of the list types we made:</p><pre><code class="language-csharp">var mx = new MyList&lt;int&gt;([1, 2, 3]);
var my = AddAnything(mx, mx);        // [1, 2, 3, 1, 2, 3]

var nx = new MyString(&quot;Hello&quot;);
var ny = AddAnything(nx, nx);        // &quot;HelloHello&quot;
</code></pre><p>You may think: <em>&quot;so what, we could create addable interfaces before?&quot;</em> &#x2013; and you&apos;d be right.  But, the difference here is that the <code>static</code> members don&apos;t need an instance.  So, now we can do this:</p><pre><code class="language-csharp">public interface Addable&lt;SELF&gt; where SELF : Addable&lt;SELF&gt;
{
    public static abstract SELF Empty { get; }
    public static abstract SELF Add(SELF x, SELF y);
}
</code></pre><p>We&apos;ve added an <code>Empty</code> property that presumably returns the &apos;zero&apos; value for for <code>SELF</code>.</p><p>Now we can extend our types:</p><pre><code class="language-csharp">public record MyList&lt;A&gt;(A[] values) : 
    Addable&lt;MyList&lt;A&gt;&gt;
{
    public static MyList&lt;A&gt; Empty { get; } = new ([]);
    
    public static MyList&lt;A&gt; Add(MyList&lt;A&gt; x, MyList&lt;A&gt; y) =&gt; 
        new (x.values.Concat(y.values).ToArray());
}

public record MyString(string value) : 
    Addable&lt;MyString&gt;
{
    public static MyString Empty { get; } = new(&quot;&quot;);
    
    public static MyString Add(MyString x, MyString y) =&gt; 
        new (x.value + y.value);
}</code></pre><p>With that we can write some more general functions that work with <code>Addable</code> values.  First, we&apos;ll create <code>FoldMap</code> which iterates over a sequence of values, mapping them into <code>Addable</code> values, and then aggregating them as it goes using <code>Add</code>:</p><pre><code class="language-csharp">B FoldMap&lt;A, B&gt;(IEnumerable&lt;A&gt; xs, Func&lt;A, B&gt; f) where B : Addable&lt;B&gt;
{
    var r = B.Empty;
    foreach (var x in xs)
    {
        r = B.Add(r, f(x));
    }
    return r;
}</code></pre><p>Once we have that we can write a general concatenation function:</p><pre><code class="language-csharp">A Concat&lt;A&gt;(IEnumerable&lt;A&gt; xs) where A : Addable&lt;A&gt; =&gt;
    FoldMap(xs, x =&gt; x);</code></pre><p>And so we&apos;ve managed to generalise folding and concatenation (for completely distinct types) in a way that wasn&apos;t possible before in C# (other than with the ad-hoc polymorphism trick leveraged in language-ext <code>v4</code>, but let&apos;s ignore that for now as it&apos;s not particularly attractive as a technique) .  </p><blockquote>Another major improvement is the return types from the members are the concrete value and not a (potentially boxed) <code>Addable&lt;A&gt;</code> &#x2013; which has been a classic problem of using interfaces in C#.</blockquote><p>The eagle-eyed amongst you will recognise that the <code>Addable</code> structure is a <code>Monoid</code>.  In fact a <code>Semigroup</code> does &apos;adding&apos; (in reality any associative binary operation) and a <code>Monoid</code> inherits <code>Semigroup</code> and extends it with an identity element (<code>Empty</code>).  </p><p>So, let&apos;s refactor <code>Addable</code>:</p><pre><code class="language-csharp">public interface Semigroup&lt;A&gt; 
    where A : Semigroup&lt;A&gt;
{
    public static abstract A operator+ (A x, A y);
}

public interface Monoid&lt;A&gt; : Semigroup&lt;A&gt;
    where A : Monoid&lt;A&gt;
{
    public static abstract A Empty { get; }
}
</code></pre><blockquote>This is the first major change in language-ext <code>v5</code>.  Semigroups and Monoids are now types that you must inherit to make something into a semigroup or monoidal.  You can see the new implementations <a href="https://github.com/louthy/language-ext/blob/v5-transducers/LanguageExt.Core/Traits/Semigroup/Semigroup.cs?ref=paullouth.com">here</a> and <a href="https://github.com/louthy/language-ext/blob/v5-transducers/LanguageExt.Core/Traits/Monoid/Monoid.cs?ref=paullouth.com">here</a>. </blockquote><p>The big problem here is that we can&apos;t make types, that we don&apos;t own, into semigroups and monoids.  That is, we don&apos;t have ad-hoc polymorphism.  And so, we can&apos;t make <code>string</code> monoidal, or integers, or any type that is not under our control.  </p><p>However, we can use the technique I have already shown above, of wrapping up an existing type in a small container type that <em>does </em>have the traits we need.  It necessitates a small conversion step at the point of monoidal-usage, but other than that, it&apos;s relatively painless, if not entirely elegant.</p><blockquote>This decision is a major shift from the ad-hoc polymorphism approach of earlier versions of language-ext.  I believe it&apos;s the pragmatic decision that leads to more elegant code.  The slightly less elegant part is when using types that don&apos;t belong to you, but I feel the trade is the right one.  </blockquote><p>Monoids are relatively simple types, what about something more complex?  Could we make <code>Select</code> from LINQ into something more concrete and not a hack in the compiler?</p><p>Let&apos;s try the same trait-like technique from before, let&apos;s call the trait <code>Mappable</code> for no apparent reason (some of you will know where I&apos;m going with this!):</p><pre><code class="language-csharp">public interface Mappable&lt;SELF&gt;
    where SELF : Mappable&lt;SELF&gt;
{
    public static abstract SELF Select&lt;A, B&gt;(SELF list, Func&lt;A, B&gt; f);
}
</code></pre><p>If we try to implement this everything goes wrong.  We can&apos;t get the <code>X</code> in the array and transform it into an <code>A</code> to give to the mapping function <code>f</code>:</p><pre><code class="language-csharp">public record MyList&lt;X&gt;(X[] values) : 
    Mappable&lt;MyList&lt;X&gt;&gt;
{
    public static MyList&lt;X&gt; Select&lt;A, B&gt;(MyList&lt;X&gt; list, Func&lt;A, B&gt; f) =&gt; 
        // Can&apos;t map an X to an A
}
</code></pre><p>What if we remove the <code>A</code> argument from <code>Select</code> and instead embed it in the trait:</p><pre><code class="language-csharp">public interface Mappable&lt;SELF, A&gt;
    where SELF : Mappable&lt;SELF, A&gt;
{
    public static abstract SELF Select&lt;B&gt;(SELF list, Func&lt;A, B&gt; f);
}</code></pre><p>It gets us closer, but now the <code>A</code> is baked into the return type of <code>Select</code>:</p><pre><code class="language-csharp">public record MyList&lt;A&gt;(A[] values) : 
    Mappable&lt;MyList&lt;A&gt;, A&gt;
{
    public static MyList&lt;A&gt; Select&lt;B&gt;(MyList&lt;A&gt; list, Func&lt;A, B&gt; f) =&gt;
        new(list.values.Select(f).ToArray()); 
}    // ^^^ MyList&lt;B&gt; doesn&apos;t type check
</code></pre><p>The problem now is that the <code>A</code> is baked into the trait, everything must work with <code>A</code> &#x2013; so even the most basic mapping of values within a collection cannot be achieved with C#.  </p><p><em>And the reason that this can&apos;t be done is because C# doesn&apos;t have higher-kinded types...</em></p><h2 id="what-are-higher-kinds">What are higher kinds?</h2><p>Simply, higher-kinded types are types that are parameterised by other types.  <code>Option&lt;int&gt;</code> is a lower-kinded type, because it is entirely concrete.  <code>Option&lt;A&gt;</code> is a higher-kinded type, because it has a parameter <code>A</code> that can be used to construct a new type (like <code>Option&lt;int&gt;</code>, <code>Option&lt;string&gt;</code>, etc.)</p><blockquote>If you think of types like functions, it&apos;s a function that takes one argument (a type) and returns a result (a type).  These are the fundamentals of generics.</blockquote><p>Obviously, we already have this capability in C#, so why am I trying so hard to get higher-kinds into C#?  Well, it&apos;s the generalisation of the principle of parameterisation that is desired.  That is, if we can make the <code>A</code> in <code>Option&lt;A&gt;</code> a parameter, why can&apos;t we make the <code>Option</code> part a parameter:  <code>F&lt;A&gt;</code> ?  This isn&apos;t allowed in C#. And, it&apos;s really needed!  </p><p>It&apos;s not just that I want to add functors, applicatives, and monads to our ecosystem.  The C# compiler itself is crying out for higher-kinds...</p><p>There are loads of <em>&apos;magic functions&apos;</em> in the language: <code>Select</code>, <code>SelectMany</code>, <code>Where</code>, <code>Join</code>, <code>GroupJoin</code>, <code>GetEnumerator</code>, <code>GetAwaiter</code>, <code>Add</code> (on collections that implement <code>IEnumerable</code>), index initialisers <code>[this]</code>, the new collection initialisers...  </p><p>There are more of these magic functions, but I have forgotten them all &#x2013; which highlights a major problem with this &apos;magic&apos; approach &#x2013; total lack of <em>discoverability</em>.  The magic functions are all hacks by the C# language team to bring in higher-kinded &#x2013;  ad-hoc &#x2013; <em>traits</em> into C# without doing the heavy-lifting of making it an actual feature that we can all use.  </p><blockquote>It seems each time the C# team needs higher-kinds &#x2013;  as evidenced by these magic functions &#x2013; they just hack the compiler and leave the rest of us wanting.  I find this really sad, because it&apos;s clear there&apos;s a need and they won&apos;t address it.</blockquote><h2 id="kf-a">K&lt;F, A&gt;</h2><p><a href="https://github.com/louthy/language-ext/blob/v5.0.0-beta-54/LanguageExt.Core/Traits/K.cs?ref=paullouth.com">This</a> is the most important new type in language-ext <code>v5</code>.  It may possibly turn out to be the most impactful type ever added to language-ext.</p><p>This is the entirety of its definition:</p><pre><code class="language-csharp">public interface K&lt;F, A&gt;;
</code></pre><p>Say what?  How can a type, that has no members at all, be so important? Well, it allows:</p><ul><li>For the removal of 300,000 lines of generated and hand-written code that tried to give the impression of generalised traits.</li><li>It allows users to write their own functors, applicatives, traversables, foldables, monads, and monad-transformers that all gain default behaviours written for those traits-implementations.</li><li>Namely, it allows for higher-rank polymorphism &#x2013; higher kinds.</li></ul><p>That&apos;s enough for part 1.  For the rest of this story, <a href="https://paullouth.com/higher-kinds-in-c-with-language-ext-part-2/">check out for part 2</a>!</p><blockquote><em>Don&apos;t you just hate it when there&apos;s a cliffhanger like that at the end of an episode?  This isn&apos;t Twin Peaks or something, it&apos;s not like you&apos;re desperate to find out who killed Laura Palmer &#x2013;  you just want to know how to do higher-kinds in C# &#x2013; This is how binges happen!</em></blockquote>]]></content:encoded></item><item><title><![CDATA[Notes from a Small Functional Island]]></title><description><![CDATA[<p>Welcome to my new blog and content site for all things related to pure functional programming in C# (and probably some other languages too).  I will obviously be focusing mostly on tutorials, guides, and general commentary about my <a href="https://github.com/louthy/language-ext/?ref=paullouth.com">language-ext project</a>; but I will also take a look at the philosophy</p>]]></description><link>https://paullouth.com/coming-soon/</link><guid isPermaLink="false">65db868799e5fbe500fe886f</guid><category><![CDATA[News]]></category><dc:creator><![CDATA[Paul Louth]]></dc:creator><pubDate>Sun, 25 Feb 2024 18:27:19 GMT</pubDate><media:content url="https://paullouth.com/content/images/2024/02/bauhaus-cover-edited-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://paullouth.com/content/images/2024/02/bauhaus-cover-edited-2.png" alt="Notes from a Small Functional Island"><p>Welcome to my new blog and content site for all things related to pure functional programming in C# (and probably some other languages too).  I will obviously be focusing mostly on tutorials, guides, and general commentary about my <a href="https://github.com/louthy/language-ext/?ref=paullouth.com">language-ext project</a>; but I will also take a look at the philosophy of software engineering to try and get a deeper understanding of why pure functional programming is so effective.</p><p> Things will be up and running here shortly, but you can <a href="#/portal/">subscribe</a> in the meantime if you&apos;d like to stay up to date and receive emails when new content is published!  The site is hosted by me, so you&apos;re not giving away your personal details to some megacorp.  </p><p>However, I&apos;m sure you appreciate that creating content here as well as the rather sizeable efforts I put into building language-ext takes up a substantial amount of my time.  So, if you like what you see here or you&apos;re generally finding language-ext to be something worth rewarding, I would definitely appreciate a subscription.  That is optional though, so don&apos;t feel like you have to!</p><blockquote>If you&apos;re wondering about the name &apos;Notes from a Small Functional Island&apos;, it&apos;s a play on the excellent, and hilarious, Bill Bryson book: &apos;Notes from a Small Island&apos; about his journey around the UK before he moved back home to America.  As I am from the UK, it seems like a fitting title!</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://amzn.to/3P0Ki7g?ref=paullouth.com"><img src="https://paullouth.com/content/images/2024/02/bill-bryson.jpg" class="kg-image" alt="Notes from a Small Functional Island" loading="lazy" width="335" height="522"></a><figcaption><span style="white-space: pre-wrap;">Bill Bryson - Notes from a Small Island [</span><i><em class="italic" style="white-space: pre-wrap;">affiliate link</em></i><span style="white-space: pre-wrap;">]</span></figcaption></figure><hr><h3 id="subscribe">Subscribe</h3><p>This site is an independent publication launched in February 2024 by Paul Louth. If you subscribe today, you&apos;ll get full access to the website as well as email newsletters about new content when it&apos;s available. Your subscription makes this site continue to exist. Thank you!</p><h3 id="fresh-content-delivered">Fresh content, delivered</h3><p>Stay up to date with new content sent straight to your inbox! No more worrying about whether you missed something because of a pesky algorithm or news feed.</p><hr><h3 id></h3>]]></content:encoded></item></channel></rss>