ploeh blog https://blog.ploeh.dk danish software design en-us Mark Seemann Mon, 17 Mar 2025 14:03:01 UTC Mon, 17 Mar 2025 14:03:01 UTC Phased breaking changes https://blog.ploeh.dk/2025/03/17/phased-breaking-changes/ Mon, 17 Mar 2025 14:02:00 UTC <div id="post"> <p> <em>Giving advance warning before breaking client code.</em> </p> <p> I was recently listening to <a href="https://www.dotnetrocks.com/details/1941">Jimmy Bogard on .NET Rocks! talking about 14 versions of Automapper</a>. It made me reminisce on how I dealt with versioning of <a href="https://github.com/AutoFixture/AutoFixture/">AutFixture</a>, in the approximately ten years I helmed that project. </p> <p> Jimmy has done open source longer than I have, and it sounds as though he's found a way that works for him. When I led AutoFixture, I did things a bit differently, which I'll outline in this article. In no way do I mean to imply that that way was better than Jimmy's. It may, however, strike a chord with a reader or two, so I present it in the hope that some readers may find the following ideas useful. </p> <h3 id="ae623718cc094595b125b019f9cecd2b"> Scope <a href="#ae623718cc094595b125b019f9cecd2b">#</a> </h3> <p> This article is about versioning a code base. Typically, a code base contains 'modules' of a kind, and client code that relies on those modules. In object-oriented programming, modules are often called <em>classes</em>, but in general, what matters in this context is that some kind of API exists. </p> <p> The distinction between API and client code is most clear if you're maintaining a reusable library, and you don't know the client developers, but even internal application code has APIs and client code. The following may still be relevant if you're working in a code base together with colleagues. </p> <p> This article discusses code-level APIs. Examples include C# code that other .NET code can call, but may also apply to <a href="https://www.java.com">Java</a> objects callable from <a href="https://clojure.org/">Clojure</a>, <a href="https://www.haskell.org/">Haskell</a> code callable by other Haskell code, etc. It does not discuss versioning of <a href="https://en.wikipedia.org/wiki/REST">REST</a> APIs or other kinds of online services. I have, in the past, discussed versioning in such a context, and refer you, among other articles, to <a href="/2015/06/22/rest-implies-content-negotiation">REST implies Content Negotiation</a> and <a href="/2020/06/01/retiring-old-service-versions">Retiring old service versions</a>. </p> <p> Additionally, some of the techniques outlined here are specific to .NET, or even C#. If, as I suspect, JavaScript or other languages don't have those features, then these techniques don't apply. They're hardly universal. </p> <h3 id="2bc952afa11a410d934c3fa37f9aa475"> Semantic versioning <a href="#2bc952afa11a410d934c3fa37f9aa475">#</a> </h3> <p> The first few years of AutoFixture, I didn't use a systematic versioning scheme. That changed when I encountered <a href="https://semver.org/">Semantic Versioning</a>: In 2011 I <a href="/2011/09/06/AutoFixturegoesContinuousDeliverywithSemanticVersioning">changed AutoFixture versioning to Semantic Versioning</a>. This forced me to think explicitly about breaking changes. </p> <p> As an aside, in recent years I've encountered the notion that Semantic Versioning is somehow defunct. This is often based on the observation that Semantic Version 2.0.0 was published in 2013. Surely, if no further development has taken place, it's been abandoned by its maintainer? This may or may not be the case. Does it matter? </p> <p> The original author, <a href="https://tom.preston-werner.com/">Tom Preston-Werner</a>, may have lost interest in Semantic Versioning. Or perhaps it's simply <em>done</em>. Regardless of the underlying reasons, I find Semantic Versioning useful as it is. The fact that it hasn't changed since 2013 may be an indication that it's stable. After all, it's not a piece of software. It's a specification that helps you think about versioning, and in my opinion, it does an excellent job of that. </p> <p> As I already stated, once I started using Semantic Versioning I began to think explicitly about breaking changes. </p> <h3 id="8301d3062b2f47ae8a292396da4ade8e"> Advance warning <a href="#8301d3062b2f47ae8a292396da4ade8e">#</a> </h3> <p> Chapter 10 in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> is about making changes to existing code bases. Unless you're working on a solo project with no other programmers, changes you make impact other people. If you can, avoid breaking other people's code. The chapter discusses some techniques for that, but also briefly covers how to introduce breaking changes. Some of that chapter is based on my experience with AutoFixture. </p> <p> If your language has a way to retire an API, use it. In Java you can use the <code>@Deprecated</code> annotation, and in C# the equivalent <code>[Obsolete]</code> attribute. In C#, any client code that uses a method with the <code>[Obsolete]</code> attribute will now emit a compiler warning. </p> <p> By default, this will only be a warning, and there's certainly a risk that people don't look at those. On the other hand, if you follow my advice from Code That Fits in Your Head, you should treat warnings as errors. If you do, however, those warnings emitted by <code>[Obsolete]</code> attributes will prevent your code from compiling. Or, if you're the one who just adorned a method with that attribute, you should understand that you may just have inconvenienced someone else. </p> <p> Therefore, whenever you add such an attribute, do also add a message that tells client developers how to move on from the API that you've just retired. As an example, here's an (ASP.NET) method that handles <code>GET</code> requests for calendar resources: </p> <p> <pre>[<span style="color:#2b91af;">Obsolete</span>(<span style="color:#a31515;">&quot;Use&nbsp;Get&nbsp;method&nbsp;with&nbsp;restaurant&nbsp;ID.&quot;</span>)] [<span style="color:#2b91af;">HttpGet</span>(<span style="color:#a31515;">&quot;calendar/{year}/{month}&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ActionResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">LegacyGet</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">year</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">month</span>)</pre> </p> <p> To be honest, that message may be a bit on the terse side, but the point is that there's another method on the same class that takes an additional <code>restaurantId</code>. While I'm clearly not perfect, and should have written a more detailed message, the point is that you should make it as easy as possible for client developers to deal with the problem that you've just given them. My <a href="/2014/12/23/exception-messages-are-for-programmers">rules for exception messages</a> also apply here. </p> <p> It's been more than a decade, but as I remember it, in the AutoFixture code base, I kept a list of APIs that I intended to deprecate at the next major revision. In other words, there were methods I considered fair use in a particular major version, but that I planned to phase out over multiple revisions. There were, however, a few methods that I immediately adorned with the <code>[Obsolete]</code> attribute, because I realized that they created problems for people. </p> <p> The plan, then, was to take it up a notch when releasing a new major version. To be honest, though, I never got to execute the final steps of the plan. </p> <h3 id="0fa47e6c5e8c451fbd46ca64ff5a078f"> Escalation <a href="#0fa47e6c5e8c451fbd46ca64ff5a078f">#</a> </h3> <p> By default, the <code>[Obsolete]</code> attribute emits a warning, but by supplying <code>true</code> as a second parameter, you can turn the warning into a compiler error. </p> <p> <pre>[<span style="color:#2b91af;">Obsolete</span>(<span style="color:#a31515;">&quot;Use&nbsp;Get&nbsp;method&nbsp;with&nbsp;restaurant&nbsp;ID.&quot;</span>,&nbsp;<span style="color:blue;">true</span>)] [<span style="color:#2b91af;">HttpGet</span>(<span style="color:#a31515;">&quot;calendar/{year}/{month}&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">ActionResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">LegacyGet</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">year</span>,&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">month</span>)</pre> </p> <p> You could argue that for people who treat warnings as errors, even a warning is a breaking change, but there can be no discussion that when you flip that bit, this is certainly a breaking change. </p> <p> Thus, you should only escalate to this level when you publish a new major release. </p> <p> Code already compiled against previous versions of your deprecated code may still work, but that's it. Code isn't going to compile against an API deprecated like that. </p> <p> That's the reason it's important to give client developers ample warning. </p> <p> With AutoFixture, I personally never got to that point, because I'm not sure that I arrived at this deprecation strategy until major version 3, which then had a run from early 2013 to late 2017. In other words, the library had a run of 4½ years without breaking changes. And when major version 4 rolled around, <a href="https://github.com/AutoFixture/AutoFixture/issues/703">I'd left the project</a>. </p> <p> Even after setting the <code>error</code> flag to <code>true</code>, code already compiled against earlier versions may still be able to run against newer binaries. Thus, you still need to keep the deprecated API around for a while longer. Completely removing a deprecated method should only happen in yet another major version release. </p> <h3 id="3ad29c5ed5fe4253ac319af37ddffa0b"> Conclusion <a href="#3ad29c5ed5fe4253ac319af37ddffa0b">#</a> </h3> <p> To summarize, deprecating an API could be considered a breaking change. If you take that position, imagine that your current Semantic Version is 2.44.2. Deprecating a method would then required that you release version 3.0.0. </p> <p> In any case, you make some more changes to your code, reaching version 3.5.12. For various reasons, you decide to release version 4.0.0, in which you can also turn the <code>error</code> flag on. EVen so, the deprecated API remains in the library. </p> <p> Only in version 5.0.0 can you entirely delete it. </p> <p> Depending on how often you change major versions, this whole process may take years. I find that appropriate. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/03/17/phased-breaking-changes Appeal to aithority https://blog.ploeh.dk/2025/03/10/appeal-to-aithority/ Mon, 10 Mar 2025 14:40:00 UTC <div id="post"> <p> <em>No, it's not a typo.</em> </p> <p> A few months ago, I was listening to a semi-serious programme from the <a href="https://en.wikipedia.org/wiki/DR_P1">Danish public service radio</a>. This is a weekly programme about language that I always listen to as a podcast. The host is the backbone of the show, but in addition to new guests each week, he's flanked by a regular expert who is highly qualified to answer questions about etymology, grammar, semantics, etc. </p> <p> In the episode I'm describing, the expert got a question that a listener had previously emailed. To answer, (s)he started like this (and I'm paraphrasing): <em>I don't actually know the answer to this question, so I did what everyone does these days, when they don't know the answer: I asked ChatGPT.</em> </p> <p> (S)he then proceeded to read aloud what ChatGPT had answered, and concluded with some remarks along the lines that that answer sounded quite plausible. </p> <p> If I used ten to twenty hours of my time re-listening to every episode from the past few months, I could find the particular episode, link to it, transcribe the exact words, and translate them to English to the best of my abilities. I am, however, not going to do that. First, I'm not inclined to use that much time writing an essay on which I make no income. Second, my aim is not to point fingers at anyone in particular, so I'm being deliberately vague. As you may have noticed, I've even masked the person's sex. Not because I don't remember, but to avoid singling out anyone. </p> <p> The expert in question is a regular of the programme, and I've heard him or her give good and knowledgeable answers to many tricky questions. As far as I could tell, this particular question was unanswerable, along the lines of <em>why is 'table' called 'table' rather than 'griungth'?</em> </p> <p> The correct answer would have been <em>I don't know, and I don't think anyone else does.</em> </p> <p> Being a veteran of the programme, (s)he must have realized on beforehand that this wouldn't be good radio, and instead decided to keep it light-hearted. </p> <p> I get that, and I wouldn't be writing about it now if it doesn't look like an example of an increasing trend. </p> <p> People are using large language models (LLMs) to advocate for their positions. </p> <h3 id="27bb7d65cc8746f09d92f650f0a612eb"> Appeal to authority <a href="#27bb7d65cc8746f09d92f650f0a612eb">#</a> </h3> <p> <a href="https://en.wikipedia.org/wiki/Argument_from_authority">Appeal to authority</a> is no new technique in discourse. </p> <blockquote> <p> "You may also, should it be necessary, not only twist your authorities, but actually falsify them, or quote something which you have invented entirely yourself. As a rule, your opponent has no books at hand, and could not use them if he had." </p> <footer><cite><a href="https://en.wikipedia.org/wiki/The_Art_of_Being_Right">The Art of Being Right</a></cite>, <a href="https://en.wikipedia.org/wiki/Arthur_Schopenhauer">Arthur Schopenhauer</a>, 1831</footer> </blockquote> <p> This seems similar to how people have begun using so-called artificial intelligence (AI) to do their arguing for them. We may, instead, call this <em>appeal to aithority</em>. </p> <h3 id="535b5c4b352241f9bfd089677757b18f"> Epistemological cul-de-sac <a href="#535b5c4b352241f9bfd089677757b18f">#</a> </h3> <p> We've all seen plenty of examples of LLMs being wrong. I'm not going to tire you with any of those here, but I did outline <a href="/2022/12/05/github-copilot-preliminary-experience-report">my experience with GitHub Copilot in 2022</a>. While these technologies may have made some advances since then, they still make basic mistakes. </p> <p> Not only that. They're also non-deterministic. Ask a system a question once, and you get one answer. Ask the same question later, and you may get a variation of the same answer, or perhaps even a contradictory answer. If someone exhibits an answer they got from an LLM as an argument in their favour, consider that they may have been asking it five or six times before they received an answer they liked. </p> <p> Finally, you can easily ask leading questions. Even if someone shows you a screen shot of a chat with an LLM, they may have clipped prior instructions that nudge the system towards a particular bias. </p> <p> I've seen people post screen shots that an LLM claims that <a href="https://fsharp.org/">F#</a> is a better programming language than C#. While I'm sympathetic to that claim, that's not an argument. Just like <a href="/2020/10/12/subjectivity">how you feel about something isn't an argument</a>. </p> <p> This phenomenon seems to be a new trend. People use answers from LLMs as evidence that they are right. I consider this an epistemological dead end. </p> <h3 id="3a509e32ddc74ecb8dc0c7bf8048156a"> Real authority <a href="#3a509e32ddc74ecb8dc0c7bf8048156a">#</a> </h3> <p> Regular readers of this blog may have noticed that I often go to great lengths to track down appropriate sources to cite. I do this for several reasons. One is simply out of respect for the people who figured out things before us. Another reason is to strengthen my own arguments. </p> <p> It may seem that I, too, appeal to authority. Indeed, I do. When not used in in the way Schopenhauer describes, citing authority is a necessary epistemological shortcut. If someone who knows much about a particular subject has reached a conclusion based on his or her work, we may (tentatively) accept the conclusion without going through all the same work. As Carl Sagan said, "If you wish to make an apple pie from scratch, you must first invent the universe." You can't do <em>all</em> basic research by yourself. At some point, you'll have to take expert assertions at face value, because you don't have the time, the education, or the money to build your own <a href="https://en.wikipedia.org/wiki/Large_Hadron_Collider">Large Hadron Collider</a>. </p> <p> Don't blindly accept an argument on the only grounds that someone famous said something, but on the other hand, there's no reason to dismiss out of hand what <a href="https://en.wikipedia.org/wiki/Albert_Einstein">Albert Einstein</a> had to say about gravity, just because you've heard that you shouldn't accept an argument based on appeal to authority. </p> <h3 id="8dbb3f507d8d49b2aa2f322d80fb4031"> Conclusion <a href="#8dbb3f507d8d49b2aa2f322d80fb4031">#</a> </h3> <p> I'm concerned that people increasingly seem to resort to LLMs to argue a case. The LLMs says this, so it must be right. </p> <p> Sometimes, people will follow up their arguments with <em>of course, it's just an AI, but...</em> and then proceed to unfold their preferred argument. Even if this seems as though the person is making a 'real' argument, starting from an LLM answer establishes a baseline to a discussion. It still lends an aura of truth to something that may be false. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/03/10/appeal-to-aithority Reactive monad https://blog.ploeh.dk/2025/03/03/reactive-monad/ Mon, 03 Mar 2025 09:30:00 UTC <div id="post"> <p> <em>IObservable&lt;T&gt; is (also) a monad.</em> </p> <p> This article is an instalment in <a href="/2022/03/28/monads">an article series about monads</a>. While the previous articles showed, in great detail, how to turn various classes into monads, this article mostly serves as a place-holder. The purpose is only to point out that you don't have to create all monads yourself. Sometimes, they come as part of a reusable library. </p> <p> <a href="http://reactivex.io">Rx</a> define such libraries, and <code>IObservable&lt;T&gt;</code> forms a monad. <a href="https://github.com/dotnet/reactive">Reactive Extensions for .NET</a> define a <code>SelectMany</code> method for <code>IObservable&lt;T&gt;</code>, so if <code>source</code> is an <code><span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">int</span>&gt;</code>, you can translate it to <code><span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;</code> like this: </p> <p> <pre><span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">dest</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">source</span>.<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;=&gt;&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Repeat</span>(<span style="color:#a31515;">&#39;x&#39;</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>));</pre> </p> <p> Since the <code>SelectMany</code> method is, indeed, called <code>SelectMany</code> and has the signature </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">static</span>&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;&nbsp;<span style="color:#74531f;">SelectMany</span>&lt;<span style="color:#2b91af;">TSource</span>,&nbsp;<span style="color:#2b91af;">TResult</span>&gt;( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">this</span>&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:#2b91af;">TSource</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">source</span>, &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Func</span>&lt;<span style="color:#2b91af;">TSource</span>,&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">selector</span>)</pre> </p> <p> you can also use C#'s query syntax: </p> <p> <pre><span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">dest</span>&nbsp;=&nbsp;<span style="color:blue;">from</span>&nbsp;i&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">source</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">from</span>&nbsp;x&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Repeat</span>(<span style="color:#a31515;">&#39;x&#39;</span>,&nbsp;i) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">select</span>&nbsp;x;</pre> </p> <p> In both of the above examples, I've explicitly declared the type of <code>dest</code> instead of using the <code>var</code> keyword. There's no practical reason to do this; I only did it to make the type clear to you. </p> <h3 id="2de8539dd63d4b1699e6656866e9615d"> Left identity <a href="#2de8539dd63d4b1699e6656866e9615d">#</a> </h3> <p> As I've already written time and again, a few test cases don't prove that any of the <a href="/2022/04/11/monad-laws">monad laws</a> hold, but they can help illustrate what they imply. For example, here's an illustration of the left-identity law, written as a parametrized <a href="https://xunit.net/">xUnit.net</a> test: </p> <p> <pre>[<span style="color:#2b91af;">Theory</span>] [<span style="color:#2b91af;">InlineData</span>(1)] [<span style="color:#2b91af;">InlineData</span>(2)] [<span style="color:#2b91af;">InlineData</span>(3)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&nbsp;<span style="font-weight:bold;color:#74531f;">LeftIdentity</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">a</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">h</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;=&gt;&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Repeat</span>(<span style="color:#a31515;">&#39;x&#39;</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">left</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Return</span>(<span style="font-weight:bold;color:#1f377f;">a</span>).<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#74531f;">h</span>).<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="font-weight:bold;color:#74531f;">h</span>(<span style="font-weight:bold;color:#1f377f;">a</span>).<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.<span style="color:#74531f;">Equal</span>(<span style="font-weight:bold;color:#1f377f;">left</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>); }</pre> </p> <p> Not only does the <a href="https://www.nuget.org/packages/System.Reactive/">System.Reactive</a> library define <em>monadic bind</em> in the form of <code>SelectMany</code>, but also <em>return</em>, with the aptly named <code>Observable.Return</code> function. .NET APIs often forget to do so explicitly, which means that I often have to go hunting for it, or guessing what the developers may have called it. Not here; thank you, Rx team. </p> <h3 id="04c23a87f0534e4495ef3d644793e1aa"> Right identity <a href="#04c23a87f0534e4495ef3d644793e1aa">#</a> </h3> <p> In the same spirit, we may write another test to illustrate the right-identity law: </p> <p> <pre>[<span style="color:#2b91af;">Theory</span>] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;foo&quot;</span>)] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;bar&quot;</span>)] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;baz&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&nbsp;<span style="font-weight:bold;color:#74531f;">RightIdentity</span>(<span style="color:blue;">string</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">a</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">f</span>(<span style="color:blue;">string</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>.<span style="font-weight:bold;color:#74531f;">ToObservable</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#74531f;">f</span>(<span style="font-weight:bold;color:#1f377f;">a</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">left</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>.<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Return</span>).<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>.<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.<span style="color:#74531f;">Equal</span>(<span style="font-weight:bold;color:#1f377f;">left</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>); }</pre> </p> <p> In both this and the previous test, you can see that the test has to <code>await</code> the observables in order to verify that the resulting collections are identical. Clearly, if you're instead dealing with infinite streams of data, you can't rely on such a simplifying assumption. For the general case, you must instead turn to other (proof) techniques to convince yourself that the laws hold. That's not my agenda here, so I'll skip that part. </p> <h3 id="8b5017e1aa3942ee8693e56eec6c060d"> Associativity <a href="#8b5017e1aa3942ee8693e56eec6c060d">#</a> </h3> <p> Finally, we may illustrate the associativity law like this: </p> <p> <pre>[<span style="color:#2b91af;">Theory</span>] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;foo&quot;</span>)] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;123&quot;</span>)] [<span style="color:#2b91af;">InlineData</span>(<span style="color:#a31515;">&quot;4t2&quot;</span>)] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">async</span>&nbsp;<span style="color:#2b91af;">Task</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Associativity</span>(<span style="color:blue;">string</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">a</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">f</span>(<span style="color:blue;">string</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>)&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>.<span style="font-weight:bold;color:#74531f;">ToObservable</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">byte</span>&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">g</span>(<span style="color:blue;">char</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">c</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(<span style="color:blue;">byte</span>.<span style="color:#74531f;">TryParse</span>(<span style="font-weight:bold;color:#1f377f;">c</span>.<span style="font-weight:bold;color:#74531f;">ToString</span>(),&nbsp;<span style="color:blue;">out</span>&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">b</span>)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Return</span>(<span style="font-weight:bold;color:#1f377f;">b</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Empty</span>&lt;<span style="color:blue;">byte</span>&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">h</span>(<span style="color:blue;">byte</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">b</span>)&nbsp;=&gt;&nbsp;<span style="color:#2b91af;">Observable</span>.<span style="color:#74531f;">Repeat</span>(<span style="font-weight:bold;color:#1f377f;">b</span>&nbsp;%&nbsp;2&nbsp;==&nbsp;0,&nbsp;<span style="font-weight:bold;color:#1f377f;">b</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IObservable</span>&lt;<span style="color:blue;">char</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#74531f;">f</span>(<span style="font-weight:bold;color:#1f377f;">a</span>); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">bool</span>&gt;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">left</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>.<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#74531f;">g</span>).<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#74531f;">h</span>).<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IList</span>&lt;<span style="color:blue;">bool</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#8f08c4;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">m</span>.<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#1f377f;">x</span>&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">g</span>(<span style="font-weight:bold;color:#1f377f;">x</span>).<span style="font-weight:bold;color:#74531f;">SelectMany</span>(<span style="font-weight:bold;color:#74531f;">h</span>)).<span style="font-weight:bold;color:#74531f;">ToList</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.<span style="color:#74531f;">Equal</span>(<span style="font-weight:bold;color:#1f377f;">left</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">right</span>); }</pre> </p> <p> This test composes three observable-producing functions in two different ways, to verify that they produce the same values. </p> <p> The first function, <code>f</code>, simply turns a string into an observable stream. The string <code>"foo"</code> becomes the stream of characters <code>'f'</code>, <code>'o'</code>, <code>'o'</code>, and so on. </p> <p> The next function, <code>g</code>, tries to parse the incoming character as a number. I've chosen <code>byte</code> as the data type, since there's no reason trying to parse a value that can, at best, be one of the digits <code>0</code> to <code>9</code> into a full 32-bit integer. A <code>byte</code> is already too large. If the character can be parsed, it's published as a byte value; if not, an empty stream of data is returned. For example, the character stream <code>'f'</code>, <code>'o'</code>, <code>'o'</code> results in three empty streams, whereas the stream <code>4</code>, <code>t</code>, <code>2</code> produces one singleton stream containing the <code>byte</code> <code>4</code>, followed by an empty stream, followed again by a stream containing the single number <code>2</code>. </p> <p> The third and final function, <code>h</code>, turns a number into a stream of Boolean values; <code>true</code> if the number is even, and <code>false</code> if it's odd. The number of values is equal to the number itself. Thus, when composed together, <code>"123"</code> becomes the stream <code>false</code>, <code>true</code>, <code>true</code>, <code>false</code>, <code>false</code>, <code>false</code>. This is true for both the <code>left</code> and the <code>right</code> list, even though they're results of two different compositions. </p> <h3 id="e4efefbebe564e30a27720fdd3f65f7f"> Conclusion <a href="#e4efefbebe564e30a27720fdd3f65f7f">#</a> </h3> <p> The point of this article is mostly that monads are commonplace. While you may discover them in your own code, they may also come in a reusable library. If you already know C# LINQ based off <code>IEnumerable&lt;T&gt;</code>, parts of Rx will be easy for you to learn. After all, it's the same abstraction, and <em>familiar abstractions make code readable</em>. </p> <p> <strong>Next:</strong> <a href="/2023/01/09/the-io-monad">The IO monad</a>. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/03/03/reactive-monad Easier encapsulation with static types https://blog.ploeh.dk/2025/02/24/easier-encapsulation-with-static-types/ Mon, 24 Feb 2025 14:05:00 UTC <div id="post"> <p> <em>A metaphor.</em> </p> <p> While I'm still <a href="/2021/08/09/am-i-stuck-in-a-local-maximum">struggling</a> with the notion that <a href="/2024/12/09/implementation-and-usage-mindsets">dynamically typed languages may have compelling advantages</a>, I keep coming back to the benefits of statically typed languages. One such benefit is how it enables the communication of contracts, as I recently discussed in <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a>. </p> <p> As usual, I base my treatment of <a href="/encapsulation-and-solid">encapsulation</a> on my reading of <a href="https://en.wikipedia.org/wiki/Bertrand_Meyer">Bertrand Meyer</a>'s seminal <a href="/ref/oosc">Object-Oriented Software Construction</a>. A major aspect of encapsulation is the explicit establishment of <em>contracts</em>. What is expected of client code before it can invoke an operation (preconditions)? What is guaranteed to be true after the operation completes (postconditions)? And what is always true of a particular data structure (invariants)? </p> <p> Contracts constitute the practical part of encapsulation. A contract can give you a rough sense of how well-encapsulated an API is: The more statements you can utter about the contract, the better encapsulation. You may even be able to take all those assertions about the contract and implement them as property-based tests. In other words, if you can think of many properties to write as tests, the API in question probably has good encapsulation. If, on the other hand, you can't think of a single precondition, postcondition, or invariant, this may indicate that encapsulation is lacking. </p> <p> Contracts are the practical part of encapsulation. The overall notion provides guidance of <em>how</em> to achieve encapsulation. Specific contracts describe <em>what</em> is possible, and <em>how</em> to successfully interact with an API. Clearly, the <em>what</em> and <em>how</em>. </p> <p> They don't, however, explain <em>why</em> encapsulation is valuable. </p> <h3 id="1a06496713174bba99d05dad211205c2"> Why encapsulate? <a href="#1a06496713174bba99d05dad211205c2">#</a> </h3> <p> Successful code bases are big. Such a code base rarely <a href="/code-that-fits-in-your-head">fits in your head</a> in its entirety. And the situation is only exacerbated by multiple programmers working concurrently on the code. Even if you knew most of the code base by heart, your team members are changing it, and you aren't going to be aware of all the modifications. </p> <p> Encapsulation offers a solution to this problem. Instead of knowing every detail of the entire code base, encapsulation should enable you to interact with an API (originally, an <em>object</em>) <em>without</em> knowing all the implementation details. This is the raison d'être of contracts. Ideally, knowing the contract and the purpose of an object and its methods should be enough. </p> <p> Imagine that you've designed an API with a strong contract. Is your work done? Not yet. Somehow, you'll have to communicate the contract to all present and future client developers. </p> <p> How do you convey a contract to potential users? I can think of a few ways. Good names are important, but <a href="/2020/11/23/good-names-are-skin-deep">only skin-deep</a>. You can also publish documentation, or use the type system. The following metaphor explores those two alternatives. </p> <h3 id="5ad0b635686f436d80a753622d6e4f22"> Doing a puzzle <a href="#5ad0b635686f436d80a753622d6e4f22">#</a> </h3> <p> When I was a boy, I had a puzzle called <em>Das verflixte Hunde-Spiel</em>, which roughly translates to <em>the confounded dog game</em>. I've <a href="/2024/10/03/das-verflixte-hunde-spiel">previously described the game and an algorithm for solving it</a>, but that's not my concern here. Rather, I'd like to discuss how one might abstract the information carried by each tile. </p> <p> <img src="/content/binary/hunde-spiel.jpg" alt="A picture of the box of the puzzle, together with the tiles spread out in unordered fashion."> </p> <p> As the picture suggests, the game consists of nine square tiles, each with two dog heads and two tails. The objective of the puzzle is to lay all nine tiles in a three-by-three grid such that all the heads fit the opposing tails. The dogs come in four different colour patterns, and each head must fit a tail of the same pattern. </p> <p> It turns out that there are umpteen variations of this kind of puzzle. This one has cartoon dogs, but you can find similar games with frogs, cola bottles, <a href="https://en.wikipedia.org/wiki/Playing_card_suit">playing card suits</a>, trains, ladybirds, fast food, flowers, baseball players, owls, etc. This suggests that a <em>generalization</em> may exist. Perhaps an abstraction, even. </p> <blockquote> <p> "Abstraction is the elimination of the irrelevant and the amplification of the essential" </p> <footer><cite>Robert C. Martin, <a href="/ref/doocautbm">Designing Object-Oriented C++ Applications Using The Booch Method</a>, ch. 00</cite></footer> </blockquote> <p> How to eliminate the irrelevant and amplify the essential of a tile? </p> <p> To recapitulate, a single tile looks like this: </p> <p> <img src="/content/binary/hundespiel-tile1.jpg" width="200" alt="One of the tiles of the Hunde-Spiel."> </p> <p> In a sense, we may regard most of the information on such a tile as 'implementation details'. In a code metaphor, imagine looking at a tile like this as being equivalent to looking at the source code of a method or function (i.e. API). That's not the <em>essence</em> we need to correctly assemble the puzzle. </p> <p> Imagine that you have to lay down the tiles according to <a href="/2024/10/03/das-verflixte-hunde-spiel">a known solution</a>. Since you already know the solution, this task only involves locating and placing each of the nine tiles. In this case, there are only nine tiles, each with four possible rotations, so if you already know what you're looking for, that is, of course, a tractable endeavour. </p> <p> Now imagine that you'd like to undertake putting together the tiles <em>without</em> having to navigate by the full information content of each tile. In programming, we often need to do this. We have to identify objects that are likely to perform some subtask for us, and we have to figure out how to interact with such an object to achieve our goals. Preferably, we'd like to be able to do this <em>without</em> having to read all the source code of the candidate object. <em>Encapsulation</em> promises that this should be possible. </p> <h3 id="f87bc2bd17584b63808bb0581eeb1523"> The backside of the tiles <a href="#f87bc2bd17584b63808bb0581eeb1523">#</a> </h3> <p> If we want to eliminate the irrelevant, we have to hide the information on each tile. As a first step, consider what happens if we flip the tiles around so that we only see their backs. </p> <p> <img src="/content/binary/empty-tile-backside.png" alt="An empty square, symbolizing the backside of a tile." width="200"> </p> <p> Obviously, each backside is entirely devoid of information, which means that we're now flying blind. Even if we know how to solve the puzzle, our only recourse is to blindly pick and rotate each of the nine tiles. As the <a href="/2024/10/03/das-verflixte-hunde-spiel">previous article</a> calculated, when picking at random, the odds of arriving at any valid solution is 1 to 5,945,425,920. Not surprisingly, total absence of information doesn't work. </p> <p> We already knew that, because, while we want to eliminate the irrelevant, we also must amplify the essential. Thus, we need to figure out what that might be. </p> <p> Perhaps we could write the essential information on the back of each tile. In the metaphor, this would correspond to writing documentation for an API. </p> <h3 id="86c6695ffa884ec28be560309779ab98"> Documentation <a href="#86c6695ffa884ec28be560309779ab98">#</a> </h3> <p> To continue the metaphor, I asked various acquaintances to each 'document' a title. I deliberately only gave them the instruction that they should enable me to assemble the puzzle based on what was on the back of each tile. Some asked for additional directions, as to format, etc., but I refused to give any. People document code in various different ways, and I wanted to capture similar variation. Let's review some of the documentation I received. </p> <p> <img src="/content/binary/tile2-doc.jpg" alt="The back of a tile, with written documentation and some arrows." width="200"> </p> <p> Since I asked around among acquaintances, all respondents were Danes, and some chose to write the documentation in Danish, as is the case with this one. </p> <p> Unless you have an explicit, enforced policy, you might run into a similar situation in software documentation. I've seen more than one example of software documentation written in Danish, simply because the programmer who wrote it didn't consider anything else than his or her native language. I'm sure most Europeans have similar experiences. </p> <p> The text on the tile says, from the top and clockwise: </p> <ul> <li>light brown dog/light snout/dark ears</li> <li>dark brown, white/snout</li> <li>orange tail/brown spots on/back</li> <li>orange tail/orange back</li> </ul> <p> Notice the disregard for capitalization rules or punctuation, a tendency among programmers that I've commented upon in <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a>. </p> <p> In addition to the text, the back of the above tile also includes six arrows. Four of them ought to be self-evident, but can you figure out what the two larger arrows indicate? </p> <p> It turns out that the person writing this piece of documentation eventually realized that the description should be mirrored, because it was on the backside of the tile. To be fair to that person, I'd asked everyone to write with a permanent marker or pen, so correcting a mistake involved either a 'hack' like the two arrows, or starting over from scratch. </p> <p> Let's look at some more 'documentation'. Another tile looks like this: </p> <p> <img src="/content/binary/tile3-doc.jpg" alt="The back of a tile, with some fairly cryptic symbols in the corners." width="200"> </p> <p> At first glance, I thought those symbols were Greek letters, but once you look at it, you start to realize what's going on. In the upper right corner, you see a stylized back and tail. Likewise, the lower left corner has a stylized face in the form of a smiley. The lines then indicate that the sides indicated by a corner has a head or tail. </p> <p> Additionally, each side is encoded with a letter. I'll leave it as an exercise for the reader to figure out what <em>G</em> and <em>B</em> indicate, but also notice the two examples of a modified <em>R</em>. The one to the right indicates <em>red with spots</em>, and the other one uses the minus symbol to indicate <em>red without spots</em>. </p> <p> On the one hand, this example does an admirable job of eliminating the irrelevant, but you may also find that it errs on the side of terseness. At the very least, it demands of the reader that he or she is already intimately familiar with the overall problem domain. You have to know the game well enough to be able to figure out that <em>R-</em> probably means <em>red without spots</em>. </p> <p> Had this been software documentation, we might have been less than happy with this level of information. It may meet formal requirements, but is perhaps too idiosyncratic or esoteric. </p> <p> Be that as it may, it's also possible to err on the other side. </p> <p> <img src="/content/binary/Tile5-doc.jpg" alt="The back of a tile, this time with an almost one-to-one replica of the picture on the front." width="200"> </p> <p> In this example, the person writing the documentation essentially copied and described every detail on the front of the tile. Having no colours available, the person instead chose to describe in words the colour of each dog. Metaphorically speaking, the documentation replicates the implementation. It doesn't eliminate any irrelevant detail, and thereby it also fails to amplify the essential. </p> <p> Here's another interesting example: </p> <p> <img src="/content/binary/tile8-doc.jpg" alt="The back of a tile, with text along all four sides." width="200"> </p> <p> The text is in Danish. From the top clockwise, it says: </p> <ul> <li>dark brown dog with blue collar</li> <li>light brown dog with red collar</li> <li>brown dog with small spots on back</li> <li>Brown dog with big spots on back</li> </ul> <p> Notice how the person writing this were aware that a tile has no natural up or down. Instead, each side is described with letters facing up when that side is up. You have to rotate the documentation in order to read all four sides. You may find that impractical, but I actually consider that to represent something essential about each tile. To me, this is positive. </p> <p> Even so, an important piece of information is missing. It doesn't say which sides have heads, and which ones have tails. </p> <p> Finally, here's one that, in my eyes, amplifies the essential and eliminates the irrelevant: </p> <p> <img src="/content/binary/tile6-doc.jpg" alt="The back of a tile, with text along all four sides." width="200"> </p> <p> Like the previous example, you have to rotate the documentation in order to read all four sides, but the text is much terser. If you ask me, <em>Grey head</em>, <em>Burnt umber tail</em>, <em>Brown tail</em>, and <em>Spotted head</em> amplifies the essential and eliminates everything else. </p> <p> Notice, however, how inconsistent the documentation is. People chose various different ways in their attempt to communicate what they found important. Some people inadvertently left out essential information. Other people provided too much information. Some people never came through, so in a few cases, documentation was entirely absent. And finally, I've hinted at this already, most people forgot to 'mirror' the information, but a few did remember. </p> <p> All of this has direct counterparts in software documentation. The level of detail you get from documentation varies greatly, and often, the information that I actually care about is absent: Can I call this method with a negative number? Does the input string need to be formatted in a particular way? Does the method ever return null? Which exceptions may it throw? </p> <p> I'm not against documentation, but it has limitations. As far as I can tell, though, that's your only option if you're working in a dynamically typed language. </p> <h3 id="dfb325aa94c6490b8ecbb36107d8be32"> Static types with limited expression <a href="#dfb325aa94c6490b8ecbb36107d8be32">#</a> </h3> <p> Can you think of a way to constrain which puzzle pieces fit together with other pieces? </p> <p> That's how <a href="https://en.wikipedia.org/wiki/Jigsaw_puzzle">jigsaw puzzles</a> work. As a first attempt, we may try to cut out out the pieces like this: </p> <p> <img src="/content/binary/one-jigsaw-tile.png" alt="An anonymous jigsaw puzzle piece" width="226"> </p> <p> This does help some, because when presented with the subtask of having to locate and find the next piece, at least we can't rotate the next piece in four different positions. Instead, we have only two options. Perhaps we'll choose to lay down the next piece like this: </p> <p> <img src="/content/binary/two-jigsaw-tiles.png" alt="Two anonymous jigsaw pieces fit together" width="426"> </p> <p> You may also decide to rotate the right piece ninety degrees clockwise, but those are your only two rotation options. </p> <p> We may decide to encode the shape of the pieces so that, say, the tabs indicate heads and the indentations indicate tails. This, at least, prevents us from joining head with head, or tail with tail. </p> <p> This strikes me as an apt metaphor for <a href="https://en.wikipedia.org/wiki/C_(programming_language)">C</a>, or how many programmers use the type systems of C# or <a href="https://www.java.com/">Java</a>. It does prevent some easily preventable mistakes, but the types still don't carry enough information to enable you to identify exactly the pieces you need. </p> <h3 id="2196a52cce924b1ab0998f6a840a3e6c"> More expressive static types <a href="#2196a52cce924b1ab0998f6a840a3e6c">#</a> </h3> <p> Static type systems come in various forms, and some are more expressive than others. To be honest, C#'s type system does come with good expressive powers, although it tends to <a href="/2019/12/16/zone-of-ceremony">require much ceremony</a>. As far as I can tell, Java's type system is on par with C#. Let's assume that we either take the time to jump through the hoops that make these type systems expressive, or that we're using a language with a more expressive type system. </p> <p> In the puzzle metaphor, we may decide to give a tile this shape: </p> <p> <img src="/content/binary/strongly-typed-tile.png" alt="A jigsaw puzzle piece with four distinct tab and indentation shapes." width="225"> </p> <p> Such a shape encodes all the information that we need, because each tab or indentation has a unique shape. We may not even have to remember exactly what a square indentation represents. If we're presented with the above tile and asked to lay down a compatible tile, we have to find one with a square tab. </p> <p> <img src="/content/binary/strongly-typed-tile-pair.png" alt="Two jigsaw puzzle pieces with distinct tab and indentation shapes, arranged so that they fit together." width="425"> </p> <p> Encoding the essential information into tile <em>shapes</em> enables us to not only prevent mistakes, but identify the correct composition of all the tiles. </p> <p> <img src="/content/binary/strongly-typed-completed-puzzle.png" alt="Completed puzzle with nine distinctly shaped pieces." width="625"> </p> <p> For years, I've thought about static types as <em>shapes</em> of objects or functions. For practical purposes, <a href="/2022/08/22/can-types-replace-validation">static types can't express everything</a> an operation may do, but I find it useful to use a good type system to my advantage. </p> <h3 id="5342222c3624472ab9b638aff7ecc65e"> Code examples <a href="#5342222c3624472ab9b638aff7ecc65e">#</a> </h3> <p> You may find this a nice metaphor, and still fail to see how it translates to actual code. I'm not going to go into details here, but rather point to existing articles that give some introductions. </p> <p> One place to start is to refactor <a href="/2015/01/19/from-primitive-obsession-to-domain-modelling">from primitive obsession to domain models</a>. Just wrapping a string or an integer in a <a href="https://www.hillelwayne.com/post/constructive/">predicative type</a> helps communicate the purpose and constraints of a data type. Consider a constructor like this: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Reservation</span>( &nbsp;&nbsp;&nbsp;&nbsp;Guid&nbsp;id, &nbsp;&nbsp;&nbsp;&nbsp;DateTime&nbsp;at, &nbsp;&nbsp;&nbsp;&nbsp;Email&nbsp;email, &nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;name, &nbsp;&nbsp;&nbsp;&nbsp;NaturalNumber&nbsp;quantity)</pre> </p> <p> While hardly sophisticated, it already communicates much information about preconditions for creating a <code>Reservation</code> object. Some of the constituent types (<code>Guid</code> and <code>DateTime</code>) are built in, so likely well-known to any developer working on a relevant code base. If you're wondering whether you can create a reservation with a negative <code>quantity</code>, the types already answer that. </p> <p> Languages with native support for <a href="https://en.wikipedia.org/wiki/Tagged_union">sum types</a> let you easily model mutually exclusive, heterogeneous closed type hierarchies, as shown in <a href="/2016/11/28/easy-domain-modelling-with-types">this example</a>: </p> <p> <pre><span style="color:blue;">type</span>&nbsp;<span style="color:teal;">PaymentService</span>&nbsp;=&nbsp;{&nbsp;Name&nbsp;:&nbsp;<span style="color:teal;">string</span>;&nbsp;Action&nbsp;:&nbsp;<span style="color:teal;">string</span>&nbsp;} <span style="color:blue;">type</span>&nbsp;<span style="color:teal;">PaymentType</span>&nbsp;= |&nbsp;<span style="color:navy;">Individual</span>&nbsp;<span style="color:blue;">of</span>&nbsp;<span style="color:teal;">PaymentService</span> |&nbsp;<span style="color:navy;">Parent</span>&nbsp;<span style="color:blue;">of</span>&nbsp;<span style="color:teal;">PaymentService</span> |&nbsp;<span style="color:navy;">Child</span>&nbsp;<span style="color:blue;">of</span>&nbsp;originalTransactionKey&nbsp;:&nbsp;<span style="color:teal;">string</span>&nbsp;*&nbsp;paymentService&nbsp;:&nbsp;<span style="color:teal;">PaymentService</span></pre> </p> <p> And if your language doesn't natively support sum types, you can <a href="/2018/06/25/visitor-as-a-sum-type">emulate them with the Visitor design pattern</a>. </p> <p> You can, in fact, do some <a href="/2025/02/03/modelling-data-relationships-with-c-types">quite sophisticated tricks even with .NET's type system</a>. </p> <h3 id="783cb14749b64aafac68d97a0096b349"> Conclusion <a href="#783cb14749b64aafac68d97a0096b349">#</a> </h3> <p> People often argue about static types with the assumption that their main use is to prevent mistakes. They can help do that, too, but I also find static types an excellent communication medium. The benefits of using a static type system to model contracts is that, when a type system is already part of a language, it's a consistent, formalized framework for communication. Instead of inconsistent and idiosyncratic documentation, you can embed much information about a contract in the types of an API. </p> <p> And indeed, not only can the types help communicate pre- and postconditions. The type checker <em>also</em> prevents errors. </p> <p> A sufficiently sophisticated type system carries more information that most people realize. When I write <a href="https://www.haskell.org/">Haskell</a> code, I often need to look up a function that I need. Contrary to other languages, I don't try to search for a function by guessing what name it might have. Rather, the <a href="https://hoogle.haskell.org/">Hoogle</a> search engine enables you to search for a function <em>by type</em>. </p> <p> Types are shapes, and shapes are like outlines of objects. Used well, they enable you to eliminate the irrelevant, and amplify the essential information about an API. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/02/24/easier-encapsulation-with-static-types In defence of multiple WiP https://blog.ploeh.dk/2025/02/17/in-defence-of-multiple-wip/ Mon, 17 Feb 2025 08:52:00 UTC <div id="post"> <p> <em>Programming isn't like factory work.</em> </p> <p> I was recently stuck on a programming problem. Specifically, <a href="https://adventofcode.com/2024/day/19">part two of an Advent of Code puzzle</a>, if you must know. As is my routine, I went for a run, which always helps to get unstuck. During the few hours away from the keyboard, I'd had a new idea. When I returned to the computer, I had my new algorithm implemented in about an hour, and it calculated the correct result in sub-second time. </p> <p> I'm not writing this to brag. On the contrary, I suck at Advent of Code (which is a major <a href="/2020/01/13/on-doing-katas">reason that I do it</a>). The point is rather that programming is fundamentally non-linear in effort. Not only are some algorithms orders of magnitudes faster than other algorithms, but it's also the case that the amount of time you put into solving a problem doesn't always correlate with the outcome. </p> <p> Sometimes, the most productive way to solve a problem is to let it rest and <em>go do something else</em>. </p> <h3 id="007252aeb07e4b0c9c514185a7f9699f"> One-piece flow <a href="#007252aeb07e4b0c9c514185a7f9699f">#</a> </h3> <p> Doesn't this conflict with the ideal of one-piece flow? That is, that you should only have one piece of work in progress (WiP). </p> <p> Yes, it does. </p> <p> It's not that I don't understand basic queue theory, haven't read <a href="/ref/the-goal">The Goal</a>, or that I'm unaware of the <a href="https://youtu.be/Yqi9Gwt-OEA?si=9qLo77p3iJZKBwcx">compelling explanations given by, among other people, Henrik Kniberg</a>. I do, myself, <a href="/2023/01/23/agilean">lean (pun intended) towards lean software development</a>. </p> <p> I only offer the following as a counterpoint to other voices. As I've described before, when I seem to disagree with the mainstream view on certain topics, the explanation may rather be that <a href="/2021/08/09/am-i-stuck-in-a-local-maximum">I'm concerned with a different problem than other people are</a>. If your problem is a dysfunctional organization where everyone have dozens of tasks in progress, nothing ever gets done because it's considered more important to start new work items than completing ongoing work, where 'utilization' is at 100% because of 'efficiency', then yes, I'd also recommend limiting WiP. </p> <p> The idea in one-piece flow is that you're only working on one thing at a time. </p> <p> <img src="/content/binary/one-piece-flow2.png" alt="One-piece flow illustrated as a series of boxes in a row."> </p> <p> Perhaps you can divide the task into subtasks, but you're only supposed to start something new when you're done with the current job. Compared to the alternative of starting a lot concurrent tasks in order to deal with wait times in the system, I agree with the argument that this is often better. One-piece flow often prompts you to take a good, hard look at where and how delays occur in your process. </p> <p> Even so, I find it ironic that most of 'the Lean squad' is so busy blaming <a href="https://en.wikipedia.org/wiki/Scientific_management">Taylorism</a> for everything that's wrong with many software development organizations, only to go advocate for another management style rooted in factory work. </p> <p> Programming isn't manufacturing. </p> <h3 id="28c7eb05dd1342d7a3140aae5618db4f"> Urgent or important <a href="#28c7eb05dd1342d7a3140aae5618db4f">#</a> </h3> <p> As <a href="https://en.wikipedia.org/wiki/Dwight_D._Eisenhower">Eisenhower</a> quoted an unnamed college president: </p> <blockquote> <p> "I have two kinds of problems, the urgent and the important. The urgent are not important, and the important are never urgent." </p> </blockquote> <p> It's hard to overstate how liberating it can be to ignore the urgent and focus on the important. Over decades, I keep returning to the realization that you often reach the best solutions to software problems by letting them stew. </p> <p> I'm sure I've already told the following story elsewhere, but it bears repeating. Back in 2009 I started an open-source project called <a href="https://github.com/AutoFixture/AutoFixture">AutoFixture</a> and also managed to convince my then-employer, <a href="https://www.safewhere.com/">Safewhere</a>, to use it in our code base. </p> <p> Maintaining or evolving AutoFixture wasn't my job, though. It was a work-related hobby, so nothing related to it was urgent. When in the office, I worked on Safewhere code, but biking back and forth between home and work, I thought about AutoFixture problems. Often, these problems would be informed by how we used it in Safewhere. My point is that the problems I was thinking about were real problems that I'd encountered in my day job, not just something I'd dreamt up for fun. </p> <p> I was mostly thinking about API designs. Given that this was ideally a general-purpose open-source project, I didn't want to solve narrow problems with specific solutions. I wanted to find general designs that would address not only the immediate concerns, but also other problems that I had yet to discover. </p> <p> Many an evening I spent trying out an idea I'd had on my bicycle. Often, it turned out that the idea wouldn't work. While that might be, in one sense, dismaying, on the other hand, it only meant that I'd <a href="https://quoteinvestigator.com/2012/07/31/edison-lot-results/">learned about yet another way that didn't work</a>. </p> <p> Because there was no pressure to release a new version of AutoFixture, I could take the time to get it right. (After a fashion. You may disagree with the notion that AutoFixture is well-designed. I designed its APIs to the best of my abilities during the decade I lead the project. And when I discovered property-based testing, I <a href="https://github.com/AutoFixture/AutoFixture/issues/703">passed on the reins</a>.) </p> <h3 id="ae07d9022e714de689fc1900d68a866d"> Get there earlier by starting later <a href="#ae07d9022e714de689fc1900d68a866d">#</a> </h3> <p> There's a 1944 science fiction short story by <a href="https://en.wikipedia.org/wiki/A._E._van_Vogt">A. E. van Vogt</a> called <a href="https://en.wikipedia.org/wiki/Far_Centaurus">Far Centaurus</a> that I'm now going to spoil. </p> <p> In it, four astronauts embark on a 500-year journey to <a href="https://en.wikipedia.org/wiki/Alpha_Centauri">Alpha Centauri</a>, using <a href="https://en.wikipedia.org/wiki/Suspended_animation_in_fiction">suspended animation</a>. When they arrive, they discover that the system is long settled, from Earth. </p> <p> During their 500 years en route, humans invented faster space travel. Even though later generations started later, they arrived earlier. They discovered a better way to get from a to b. </p> <p> Compared to one-piece flow, we may illustrate this metaphor like this: </p> <p> <img src="/content/binary/one-piece-flow-vs-thinking.png" alt="A row of boxes above another row of thinner boxes that are more spread out, but indicates an earlier finish."> </p> <p> When presented with a problem, we don't start working on it right away. Or, we do, but the work we do is <em>thinking</em> rather than typing. We may even do some prototyping at that stage, but if no good solution presents itself, we put away the problem for a while. </p> <p> We may return to the problem from time to time, and what may happen is that we realize that there's a much better, quicker way of accomplishing the goal than we first believed (as, again, <a href="/2025/02/10/geographic-hulls">recently happened to me</a>). Once we have that realization, we may initiate the work, and it it may even turn out that we're done earlier than if we'd immediately started hacking at the problem. </p> <p> By starting later, we've learned more. Like much knowledge work, software development is a profoundly non-linear endeavour. You may find a new way of doing things that are orders of magnitudes faster than what you originally had in mind. Not only in terms of <a href="https://en.wikipedia.org/wiki/Big_O_notation">big-O notation</a>, but also in terms of implementation effort. </p> <p> When doing Advent of Code, I've repeatedly been struck how the more efficient algorithm is often also simpler to implement. </p> <h3 id="95ed780f2c3b496383f1af9b68aa2b1b"> Multiple WiP <a href="#95ed780f2c3b496383f1af9b68aa2b1b">#</a> </h3> <p> As the above figure suggests, you're probably not going to spend all your time thinking or doing. The figure has plenty of air in between the activities. </p> <p> This may seem wasteful to efficiency nerds, but again: Knowledge work isn't factory work. </p> <p> You can't think by command. If you've ever tried meditating, you'll know just how hard it is to empty your mind, or in any way control what goes on in your head. Focus on your breath. Indeed, and a few minutes later you snap out of a reverie about what to make for dinner, only to discover that you were able to focus on your breath for all of ten seconds. </p> <p> As I already alluded to in the introduction, I regularly exercise during the work day. I also go grocery shopping, or do other chores. I've consistently found that I solve all hard problems when I'm <em>away</em> from the computer, not while I'm at it. I think <a href="https://en.wikipedia.org/wiki/Rich_Hickey">Rich Hickey</a> calls it hammock-driven development. </p> <p> When presented with an interesting problem, I usually can't help thinking about it. What often happens, however, is that I'm mulling over multiple interesting problems during my day. </p> <p> <img src="/content/binary/multiple-thinking-processes-interleaved.png" alt="Same diagram as above, but now with more boxes representing thinking activities interleaved among each other."> </p> <p> You could say that I actually have multiple pieces of work in progress. Some of them lie dormant for a long time, only to occasionally pop up and be put away again. Even so, I've had problems that I'd essentially given up on, only to resurface later when I'd learned a sufficient amount of new things. At that time, then, I sometimes realize that what I previously thought was impossible is actually quite simple. </p> <p> It's amazing what you can accomplish when you focus on the things that are important, rather than the things that are urgent. </p> <h3 id="216b1e2dee074e249ad8044a6ad88a97"> One size doesn't fit all <a href="#216b1e2dee074e249ad8044a6ad88a97">#</a> </h3> <p> How do I know that this will always work? How can I be sure that an orders-of-magnitude insight will occur if I just wait long enough? </p> <p> There are no guarantees. My point is rather that this happens with surprising regularity. To me, at least. </p> <p> Your software organization may include tasks that represent truly menial work. Yet, if you have too much of that, why haven't you automated it away? </p> <p> Still, I'm not going to tell anyone how to run their development team. I'm only pointing out a weakness with the common one-piece narrative: It treats work as mostly a result of effort, and as if it were somehow interchangeable with other development tasks. </p> <p> Most crucially, it models the amount of time required to complete a task as being independent of time: Whether you start a job today or in a month, it'll take <em>x</em> days to complete. </p> <p> What if, instead, the effort was an function of time (as well as other factors)? The later you start, the simpler the work might be. </p> <p> This of course doesn't happen automatically. Even if I have all my good ideas <em>away</em> from the keyboard, I still spend quite a bit of time <em>at</em> the keyboard. You need to work enough with a problem before inspiration can strike. </p> <p> I'd recommend more slack time, more walks in the park, more grocery shopping, more doing the dishes. </p> <h3 id="ea87f59e4b014bb4861e71d8b6264394"> Conclusion <a href="#ea87f59e4b014bb4861e71d8b6264394">#</a> </h3> <p> Programming is knowledge work. We may even consider it creative work. And while you can nurture creativity, you can't force it. </p> <p> I find it useful to have multiple things going on at the same time, because concurrent tasks often cross-pollinate. What I learn from engaging with one task may produce a significant insight into another, otherwise unrelated problem. The lack of urgency, the lack of deadlines, foster this approach to problem-solving. </p> <p> But I'm not going to tell you how to run your software development process. If you want to treat it as an assembly line, that's your decision. </p> <p> You'll probably get work done anyway. Months of work can save days of thinking. </p> </div> <hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/02/17/in-defence-of-multiple-wip Geographic hulls https://blog.ploeh.dk/2025/02/10/geographic-hulls/ Mon, 10 Feb 2025 07:14:00 UTC <div id="post"> <p> <em>Seven lines of Python code.</em> </p> <p> Can you tell what this is? </p> <p> <img src="/content/binary/dk-hull.svg" alt="Convex hulls of each of the major Danish islands, as well as Jutland."> </p> <p> I showed this to both my wife and my son, and they immediately recognized it for what it is. On the other hand, they're also both culturally primed for it. </p> <p> After all, it's a map of <a href="https://en.wikipedia.org/wiki/Denmark">Denmark</a>, although I've transformed each of the major islands, as well as the peninsula of <a href="https://en.wikipedia.org/wiki/Jutland">Jutland</a> to their <a href="https://en.wikipedia.org/wiki/Convex_hull">convex hulls</a>. </p> <p> Here's the original map I used for the transformation: </p> <p> <img src="/content/binary/dk-outline.svg" alt="Map of Denmark."> </p> <p> I had a reason to do this, having to do with <a href="https://en.wikipedia.org/wiki/Coastline_paradox">the coastline paradox</a>, but my underlying motivation isn't really that important for this article, since I rather want to discuss how I did it. </p> <p> The short answer is that I used <a href="https://www.python.org/">Python</a>. You have to admit that Python has a fabulous ecosystem for all kinds of data crunching, including visualizations. I'd actually geared up to implementing a <a href="https://en.wikipedia.org/wiki/Graham_scan">Graham scan</a> myself, but that turned out not to be necessary. </p> <h3 id="2c60300f58f645d7b45cad678b076ad4"> GeoPandas to the rescue <a href="#2c60300f58f645d7b45cad678b076ad4">#</a> </h3> <p> I'm a novice Python programmer, but I've used <a href="https://matplotlib.org/">Matplotlib</a> before to visualize data, so I found it natural to start with a few web searches to figure out how to get to grips with the problem. </p> <p> I quickly found <a href="https://geopandas.org/">GeoPandas</a>, which works on top of Matplotlib to render and visualize geographical data. </p> <p> My next problem was to find a data set for Denmark, which <a href="https://simplemaps.com/gis/country/dk#all">I found on SimpleMaps</a>. I chose to download and work with the <a href="https://geojson.org/">GeoJSON</a> format. </p> <p> Originally, I'd envisioned implementing a Graham scan myself. After all, <a href="/2015/10/19/visual-value-verification">I'd done that before in F#</a>, and it's a compelling <a href="/2020/01/13/on-doing-katas">exercise</a>. It turned out, however, that this function is already available in the GeoPandas API. </p> <p> I had trouble separating the data file's multi-part geometry into multiple single geometries. This meant that when I tried to find the convex hull, I got the hull of the entire map, instead of each island individually. The solution was to use the <a href="https://geopandas.org/en/stable/docs/reference/api/geopandas.GeoDataFrame.explode.html">explode</a> function. </p> <p> Once I figured that out, it turned out that all I needed was seven lines of Python code, including imports and a blank line: </p> <p> <pre><span style="color:blue;">import</span>&nbsp;geopandas&nbsp;<span style="color:blue;">as</span>&nbsp;gpd <span style="color:blue;">import</span>&nbsp;matplotlib.pyplot&nbsp;<span style="color:blue;">as</span>&nbsp;plt <span style="color:blue;">map</span>&nbsp;=&nbsp;gpd.read_file(<span style="color:#a31515;">&#39;dk.json&#39;</span>) <span style="color:blue;">map</span>.explode().boundary.plot(edgecolor=<span style="color:#a31515;">&#39;green&#39;</span>).set_axis_off() <span style="color:blue;">map</span>.explode().convex_hull.boundary.plot().set_axis_off() plt.show()</pre> </p> <p> In this script, I display the unmodified <code>map</code> before the convex hulls. This is only an artefact of my process. As I've already admitted, this is new ground for me, and I initially wanted to verify that I could even read in and display a GeoJSON file. </p> <p> For both maps I use the <code>boundary</code> property to draw only the outline of the map, rather than filled polygons. </p> <h3 id="2b5f206417b542f386497d43d1bde322"> Enveloping the map parts <a href="#2b5f206417b542f386497d43d1bde322">#</a> </h3> <p> Mostly for fun, but also to illustrate what a convex hull is, we can layer the two visualizations in a single image. In order to do that, a few changes to the code are required. </p> <p> <pre><span style="color:blue;">import</span>&nbsp;geopandas&nbsp;<span style="color:blue;">as</span>&nbsp;gpd <span style="color:blue;">import</span>&nbsp;matplotlib.pyplot&nbsp;<span style="color:blue;">as</span>&nbsp;plt <span style="color:blue;">map</span>&nbsp;=&nbsp;gpd.read_file(<span style="color:#a31515;">&#39;dk.json&#39;</span>) _,&nbsp;ax&nbsp;=&nbsp;plt.subplots() <span style="color:blue;">map</span>.explode().boundary.plot(ax=ax,&nbsp;edgecolor=<span style="color:#a31515;">&#39;green&#39;</span>).set_axis_off() <span style="color:blue;">map</span>.explode().convex_hull.boundary.plot(ax=ax).set_axis_off() plt.show()</pre> </p> <p> This little script now produces this image: </p> <p> <img src="/content/binary/dk-outlines-in-hulls.svg" alt="Map of Denmark, with each island, as well as the Jutland peninsula, enveloped in their convex hulls."> </p> <p> Those readers who know Danish geography may wonder what's going on with <a href="https://en.wikipedia.org/wiki/Falster">Falster</a>. Since it's the sixth-largest Island in Denmark, shouldn't it have its own convex hull? Yes, it should, yet here it's connected to <a href="https://en.wikipedia.org/wiki/Zealand">Zealand</a>. Granted, two bridges connect the two, but that's hardly sufficient to consider them one island. There are plenty of bridges in Denmark, so according to that criterion, most of Denmark is connected. In fact, on the above map, only <a href="https://en.wikipedia.org/wiki/Bornholm">Bornholm</a>, <a href="https://en.wikipedia.org/wiki/Sams%C3%B8">Samsø</a>, <a href="https://en.wikipedia.org/wiki/L%C3%A6s%C3%B8">Læsø</a>, <a href="https://en.wikipedia.org/wiki/%C3%86r%C3%B8">Ærø</a>, <a href="https://en.wikipedia.org/wiki/Fan%C3%B8">Fanø</a>, and <a href="https://en.wikipedia.org/wiki/Anholt_(Denmark)">Anholt</a> would then remain as islands. </p> <p> Rather, this only highlights the quality, or lack thereof, of the data set. I don't want to complain about a free resource, and the data set has served my purposes well enough. I mostly point this out in case readers were puzzled about this. In fact, a similar case applies to <a href="https://en.wikipedia.org/wiki/North_Jutlandic_Island">Nørrejyske Ø</a>, which in the GeoJSON map is connected to Jutland at <a href="https://en.wikipedia.org/wiki/Aalborg">Aalborg</a>. Yes, there's a bridge there. No, that shouldn't qualify as a land connection. </p> <h3 id="92812a33519c47d3a90b20a447ddb7dc"> Other countries <a href="#92812a33519c47d3a90b20a447ddb7dc">#</a> </h3> <p> As you may have noticed, apart from the hard-coded file name, nothing in the code is specific to Denmark. This means that you can play around with other countries. Here I've downloaded various GeoJSON data sets from <a href="https://geojson-maps.kyd.au/">GeoJSON Maps of the globe</a>, which seems to be using the same source data set that the Danish data set is also based on. In other words, if I download the file for Denmark from that site, it looks exactly as above. </p> <p> Can you guess which country this is? </p> <p> <img src="/content/binary/gr-outline.svg" alt="Convex hull of the Greek mainland, and hulls of many Greek islands." title="Convex hull of the Greek mainland, and hulls of many Greek islands."> </p> <p> Or this one? </p> <p> <img src="/content/binary/jp-outline.svg" alt="Convex hull of each larger island of Japan." title="Convex hull of each larger island of Japan."> </p> <p> While this is all good fun, not all countries have interesting convex hull: </p> <p> <img src="/content/binary/ch-outline.svg" alt="Convex hull of Switzerland." title="Convex hull of Switzerland."> </p> <p> While I'll let you have a bit of fun guessing, you can hover your cursor over each image to reveal which country it is. </p> <h3 id="ad89b110fca040ebb37db7788ddcf6d6"> Conclusion <a href="#ad89b110fca040ebb37db7788ddcf6d6">#</a> </h3> <p> Your default position when working with Python should probably be: <em>There's already a library for that.</em> </p> <p> In this article, I've described how I wanted to show Denmark, but only the convex hull of each of the larger islands, as well as the Jutland peninsula. Of course, there was already a library for that, so that I only needed to write seven lines of code to produce the figures I wanted. </p> <p> Granted, it took a few hours of research to put those seven lines together, but I'm only a novice Python programmer, and I'm sure an old hand could do it much faster. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/02/10/geographic-hulls Modelling data relationships with C# types https://blog.ploeh.dk/2025/02/03/modelling-data-relationships-with-c-types/ Mon, 03 Feb 2025 07:24:00 UTC <div id="post"> <p> <em>A C# example implementation of Ghosts of Departed Proofs.</em> </p> <p> This article continues where <a href="/2025/01/20/modelling-data-relationships-with-f-types">Modelling data relationships with F# types</a> left off. It ports the <a href="https://fsharp.org/">F#</a> example code to C#. If you don't read F# source code, you may instead want to read <a href="/2024/12/23/implementing-rod-cutting">Implementing rod-cutting</a> to get a sense of the problem being addressed. </p> <p> I'm going to assume that you've read enough of the previous articles to get a sense of the example, but in short, this article examines if it's possible to use the type system to model data relationships. Specifically, we have methods that operate on a collection and a number. The precondition for calling these methods is that the number is a valid (one-based) index into the collection. </p> <p> While you would typically implement such a precondition with a <a href="https://en.wikipedia.org/wiki/Guard_(computer_science)">Guard Clause</a> and communicate it via documentation, you can also use the <em>Ghosts of Departed Proofs</em> technique to instead leverage the type system. Please see <a href="/2025/01/20/modelling-data-relationships-with-f-types">the previous article for an overview</a>. </p> <p> That said, I'll repeat one point here: The purpose of these articles is to showcase a technique, using a simple example to make it, I hope, sufficiently clear what's going on. All this machinery is hardly warranted for an example as simple as this. All of this is a demonstration, not a recommendation. </p> <h3 id="24f5e14404424695aca0a2c7e049b0a5"> Size proofs <a href="#24f5e14404424695aca0a2c7e049b0a5">#</a> </h3> <p> As in the previous article, we may start by defining what a 'size proof' looks like. In C#, it may <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatically</a> be a class with an <code>internal</code> constructor. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;Value&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">internal</span>&nbsp;<span style="color:#2b91af;">Size</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">value</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Value&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">value</span>; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Also&nbsp;override&nbsp;ToString,&nbsp;Equals,&nbsp;and&nbsp;GetHashCode...</span> }</pre> </p> <p> Since the constructor is <code>internal</code> it means that client code can't create <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> instances, and thereby client code can't decide a concrete type for the phantom type <code>T</code>. </p> <h3 id="0f22adf378da484b8dc85e372f82a0d6"> Issuing size proofs <a href="#0f22adf378da484b8dc85e372f82a0d6">#</a> </h3> <p> How may client code create <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects? It may ask a <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> object to issue a proof: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:blue;">int</span>&gt;&nbsp;Prices&nbsp;{&nbsp;<span style="color:blue;">get</span>;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">internal</span>&nbsp;<span style="color:#2b91af;">PriceList</span>(<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:blue;">int</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Prices&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;?&nbsp;<span style="font-weight:bold;color:#74531f;">TryCreateSize</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(0&nbsp;&lt;&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;&amp;&amp;&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;&lt;=&nbsp;Prices.Count) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="font-weight:bold;color:#1f377f;">candidate</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">null</span>; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;More&nbsp;members&nbsp;go&nbsp;here...</span></pre> </p> <p> If the requested <code>candidate</code> integer represents a valid (one-indexed) position in the <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> object, the return value is a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> object that contains the <code>candidate</code>. If, on the other hand, the <code>candidate</code> isn't in the valid range, no object is returned. </p> <p> Since both <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> and <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> classes are immutable, once a 'size proof' has been issued, it remains valid. As I've previously argued, <a href="/2024/06/12/simpler-encapsulation-with-immutability">immutability makes encapsulation simpler</a>. </p> <p> This kind of API does, however, look like it's <a href="https://en.wikipedia.org/wiki/Turtles_all_the_way_down">turtles all the way down</a>. After all, the <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> constructor is also <code>internal</code>. Now the question becomes: How does client code create <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects? </p> <p> The short answer is that it doesn't. Instead, it'll be given an object by the library API. You'll see how that works later, but first, let's review what such an API enables us to express. </p> <h3 id="079355423c6d4a7d8daaeffc08661adb"> Proof-based Cut API <a href="#079355423c6d4a7d8daaeffc08661adb">#</a> </h3> <p> As described in <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a>, returning a collection of 'cut' objects better communicates postconditions than returning a tuple of two arrays, as <a href="/2024/12/23/implementing-rod-cutting">the original algorithm suggested</a>. In other words, we're going to need a type for that. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">record</span>&nbsp;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">Revenue</span>,&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">Size</span>);</pre> </p> <p> In this case we can get by with a simple <a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/record">record type</a>. Since one of the properties is of the type <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code>, client code can't create <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> instances, just like it can't create <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> or <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects. This is what we want, because a <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> object encapsulates a proof that it's valid, related to the original collection of prices. </p> <p> We can now define the <code>Cut</code> method as an instance method on <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code>. Notice how all the <code>T</code> type arguments line up. As input, the <code>Cut</code> method only accepts <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> proofs issued by a compatible price list. This is enforced at compile time, not at run time. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">Cut</span>(<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;=&nbsp;Prices.<span style="font-weight:bold;color:#74531f;">Prepend</span>(0).<span style="font-weight:bold;color:#74531f;">ToArray</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:blue;">int</span>[<span style="font-weight:bold;color:#1f377f;">n</span>.Value&nbsp;+&nbsp;1]; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:blue;">int</span>[<span style="font-weight:bold;color:#1f377f;">n</span>.Value&nbsp;+&nbsp;1]; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>[0]&nbsp;=&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">for</span>&nbsp;(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;=&nbsp;1;&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>.Value;&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>++) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">q</span>&nbsp;=&nbsp;<span style="color:blue;">int</span>.MinValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">for</span>&nbsp;(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;=&nbsp;1;&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>;&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>++) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>[<span style="font-weight:bold;color:#1f377f;">i</span>]&nbsp;+&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>[<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;-&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">q</span>&nbsp;&lt;&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">q</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>[<span style="font-weight:bold;color:#1f377f;">j</span>]&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>[<span style="font-weight:bold;color:#1f377f;">j</span>]&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">q</span>; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">List</span>&lt;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">for</span>&nbsp;(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;=&nbsp;1;&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>.Value;&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>++) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenue</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>[<span style="font-weight:bold;color:#1f377f;">i</span>]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">size</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="font-weight:bold;color:#1f377f;">s</span>[<span style="font-weight:bold;color:#1f377f;">i</span>]); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>.<span style="font-weight:bold;color:#74531f;">Add</span>(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="font-weight:bold;color:#1f377f;">revenue</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">size</span>)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>; }</pre> </p> <p> For good measure, I'm showing the entire implementation, but you only need to pay attention to the method signature. The point is that <code>n</code> is constrained <em>by the type system</em> to be in a valid range. </p> <h3 id="ce55a32904434bd99c7f42d896fa7102"> Proof-based Solve API <a href="#ce55a32904434bd99c7f42d896fa7102">#</a> </h3> <p> The same technique can be applied to the <code>Solve</code> method. Just align the <code>T</code>s. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">Solve</span>(<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#74531f;">Cut</span>(<span style="font-weight:bold;color:#1f377f;">n</span>).<span style="font-weight:bold;color:#74531f;">ToArray</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">sizes</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">List</span>&lt;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">size</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">while</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">size</span>.Value&nbsp;&gt;&nbsp;0) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">sizes</span>.<span style="font-weight:bold;color:#74531f;">Add</span>(<span style="font-weight:bold;color:#1f377f;">cuts</span>[<span style="font-weight:bold;color:#1f377f;">size</span>.Value&nbsp;-&nbsp;1].Size); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">size</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="font-weight:bold;color:#1f377f;">size</span>.Value&nbsp;-&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>[<span style="font-weight:bold;color:#1f377f;">size</span>.Value&nbsp;-&nbsp;1].Size.Value); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">sizes</span>; }</pre> </p> <p> This is another instance method on <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code>, which is where <code>T</code> is defined. </p> <h3 id="57994590468c40fa87ba24f0d158720b"> Proof-based revenue API <a href="#57994590468c40fa87ba24f0d158720b">#</a> </h3> <p> Finally, we may also implement a method to calculate the revenue from a given sequence of cuts. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#74531f;">CalculateRevenue</span>(<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">arr</span>&nbsp;=&nbsp;Prices.<span style="font-weight:bold;color:#74531f;">ToArray</span>(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>.<span style="font-weight:bold;color:#74531f;">Sum</span>(<span style="font-weight:bold;color:#1f377f;">c</span>&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">arr</span>[<span style="font-weight:bold;color:#1f377f;">c</span>.Value&nbsp;-&nbsp;1]); }</pre> </p> <p> Not surprisingly, I hope, <code>CalculateRevenue</code> is another instance method on <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code>. The <code>cuts</code> will typically come from a call to <code>Solve</code>, but it's entirely possible for client code to create an ad-hoc collection of <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects by repeatedly calling <code>TryCreateSize</code>. </p> <h3 id="97eba480d25e4ed8a5f7b8b0efb3a528"> Running client code <a href="#97eba480d25e4ed8a5f7b8b0efb3a528">#</a> </h3> <p> How does client code use this API? It calls an <code>Accept</code> method with an implementation of this interface: </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">interface</span>&nbsp;<span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">TResult</span>&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>); }</pre> </p> <p> Why 'visitor'? This doesn't quite look like a <a href="https://en.wikipedia.org/wiki/Visitor_pattern">Visitor</a>, and yet, it still does. </p> <p> Imagine, for a moment, that we could enumerate all types that <code>T</code> could inhabit. </p> <p> <pre><span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">Type1</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>); <span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">Type2</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>); <span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">Type3</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>); <span style="color:green;">//&nbsp;⋮</span> <span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">TypeN</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>);</pre> </p> <p> Clearly we can't do that, since <code>T</code> is infinite, but <em>if</em> we could, the interface would look like a Visitor. </p> <p> I find the situation sufficiently similar to name the interface with the <em>Visitor</em> suffix. Now we only need a class with an <code>Accept</code> method. </p> <p> <pre><span style="color:blue;">public</span>&nbsp;<span style="color:blue;">sealed</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">RodCutter</span>(<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;<span style="color:blue;">int</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">TResult</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Accept</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;(<span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">visitor</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">visitor</span>.<span style="font-weight:bold;color:#74531f;">Visit</span>(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:blue;">object</span>&gt;(<span style="font-weight:bold;color:#1f377f;">prices</span>)); &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> Client code may create a <code>RodCutter</code> object, as well as one or more classes that implement <code><span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;</code>, and in this way interact with the library API. </p> <p> Let's see some examples. We'll start with the original <a href="/ref/clrs">CLRS</a> example, written as an <a href="https://xunit.net/">xUnit.net</a> test. </p> <p> <pre>[<span style="color:#2b91af;">Fact</span>] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="font-weight:bold;color:#74531f;">ClrsExample</span>() { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">RodCutter</span>([1,&nbsp;5,&nbsp;8,&nbsp;9,&nbsp;10,&nbsp;17,&nbsp;17,&nbsp;20,&nbsp;24,&nbsp;30]); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">sut</span>.<span style="font-weight:bold;color:#74531f;">Accept</span>(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">CutRodVisitor</span>(10)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">expected</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>[]&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;1,&nbsp;&nbsp;1), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;5,&nbsp;&nbsp;2), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;8,&nbsp;&nbsp;3), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(10,&nbsp;&nbsp;2), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(13,&nbsp;&nbsp;2), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(17,&nbsp;&nbsp;6), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(18,&nbsp;&nbsp;1), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(22,&nbsp;&nbsp;2), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(25,&nbsp;&nbsp;3), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(30,&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;}; &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.<span style="color:#74531f;">Equal</span>(<span style="font-weight:bold;color:#1f377f;">expected</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>); }</pre> </p> <p> <code>CutRodVisitor</code> is a nested class that implements the <code><span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">TResult</span>&gt;</code> interface: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">CutRodVisitor</span>(<span style="color:blue;">int</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;: &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)&gt;&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;<span style="color:#2b91af;">IReadOnlyCollection</span>&lt;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>.<span style="font-weight:bold;color:#74531f;">TryCreateSize</span>(<span style="font-weight:bold;color:#1f377f;">i</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;[]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>.<span style="font-weight:bold;color:#74531f;">Cut</span>(<span style="font-weight:bold;color:#1f377f;">n</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>.<span style="font-weight:bold;color:#74531f;">Select</span>(<span style="font-weight:bold;color:#1f377f;">c</span>&nbsp;=&gt;&nbsp;(<span style="font-weight:bold;color:#1f377f;">c</span>.Revenue,&nbsp;<span style="font-weight:bold;color:#1f377f;">c</span>.Size.Value)).<span style="font-weight:bold;color:#74531f;">ToArray</span>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> The <code>CutRodVisitor</code> class returns a collection of tuples. Why doesn't it just return <code>cuts</code> directly? </p> <p> It can't, because it wouldn't type-check. Think about it for a moment. When you implement the interface, you need to pick a type for <code>TResult</code>. You can't, however, declare it to implement <code><span style="color:#2b91af;">IPriceListVisitor</span>&lt;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">T</span>&gt;&gt;</code> (where <code>T</code> would be the <code>T</code> from <code><span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code>), because at the class level, you don't know what <code>T</code> is. Neither does the compiler. </p> <p> Your <code><span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> implementation must work for <em>any</em> <code>T</code>. </p> <h3 id="39d9ed0b81044e5a8f7ac990cd457fad"> Preventing misalignment <a href="#39d9ed0b81044e5a8f7ac990cd457fad">#</a> </h3> <p> Finally, here's a demonstration of how the phantom type prevents confusing or mixing up two (or more) different price lists. Consider this rather artificial example: </p> <p> <pre>[<span style="color:#2b91af;">Fact</span>] <span style="color:blue;">public</span>&nbsp;<span style="color:blue;">void</span>&nbsp;<span style="font-weight:bold;color:#74531f;">NestTwoSolutions</span>() { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">sut</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">RodCutter</span>([1,&nbsp;2,&nbsp;2]); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">inner</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">RodCutter</span>([1]); &nbsp;&nbsp;&nbsp;&nbsp;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)?&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">sut</span>.<span style="font-weight:bold;color:#74531f;">Accept</span>(<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">NestedRevenueVisitor</span>(<span style="font-weight:bold;color:#1f377f;">inner</span>)); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Assert</span>.<span style="color:#74531f;">Equal</span>((3,&nbsp;1),&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>); }</pre> </p> <p> This unit test creates two price arrays and calls <code>Accept</code> on one of them (the 'outer' one, you may say), while passing the <code>inner</code> one to the Visitor, which at first glance just looks like this: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">NestedRevenueVisitor</span>(<span style="color:#2b91af;">RodCutter</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">inner</span>)&nbsp;: &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">IPriceListVisitor</span>&lt;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)?&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)?&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">inner</span>.<span style="font-weight:bold;color:#74531f;">Accept</span>(<span style="color:blue;">new</span>&nbsp;InnerRevenueVisitor&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="font-weight:bold;color:#1f377f;">priceList</span>)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Inner&nbsp;visitor&nbsp;goes&nbsp;here...</span> }</pre> </p> <p> Notice that it only delegates to yet another Visitor, passing the 'outer' <code>priceList</code> as a constructor parameter to the next Visitor. The purpose of this is to bring two <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;</code> objects in scope at the same time. This will enable us to examine what happens if we make a programming mistake. </p> <p> First, however, here's the proper, working implementation <em>without</em> mistakes: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">class</span>&nbsp;<span style="color:#2b91af;">InnerRevenueVisitor</span>&lt;<span style="color:#2b91af;">T</span>&gt;(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList1</span>)&nbsp;:&nbsp;<span style="color:#2b91af;">IPriceListVisitor</span>&lt;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)?&gt; { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">public</span>&nbsp;(<span style="color:blue;">int</span>,&nbsp;<span style="color:blue;">int</span>)?&nbsp;<span style="font-weight:bold;color:#74531f;">Visit</span>&lt;<span style="color:#2b91af;">T1</span>&gt;(<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">T1</span>&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList2</span>) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n1</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList1</span>.<span style="font-weight:bold;color:#74531f;">TryCreateSize</span>(3); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">n1</span>&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">null</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts1</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList1</span>.<span style="font-weight:bold;color:#74531f;">Solve</span>(<span style="font-weight:bold;color:#1f377f;">n1</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenue1</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList1</span>.<span style="font-weight:bold;color:#74531f;">CalculateRevenue</span>(<span style="font-weight:bold;color:#1f377f;">cuts1</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n2</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList2</span>.<span style="font-weight:bold;color:#74531f;">TryCreateSize</span>(1); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">n2</span>&nbsp;<span style="color:blue;">is</span>&nbsp;<span style="color:blue;">null</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">null</span>; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts2</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList2</span>.<span style="font-weight:bold;color:#74531f;">Solve</span>(<span style="font-weight:bold;color:#1f377f;">n2</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenue2</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">priceList2</span>.<span style="font-weight:bold;color:#74531f;">CalculateRevenue</span>(<span style="font-weight:bold;color:#1f377f;">cuts2</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">revenue1</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">revenue2</span>); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} }</pre> </p> <p> Notice how both <code>priceList1</code> and <code>priceList2</code> are now both in scope. So far, they're <em>not</em> mixed up, so the <code>Visit</code> implementation queries first one and then another for the optimal revenue. If all works well (which it does), it returns a tuple with the two revenues. </p> <p> What happens if I make a mistake? What if, for example, I write <code>priceList2.Solve(n1)</code>? It shouldn't be possible to use <code>n1</code>, which was issued by <code>pricelist1</code>, with <code>priceList2</code>. And indeed this isn't possible. With that mistake, the code doesn't compile. The compiler error is: </p> <blockquote> <p> Argument 1: cannot convert from 'Ploeh.Samples.RodCutting.Size&lt;T&gt;' to 'Ploeh.Samples.RodCutting.Size&lt;T1&gt;' </p> </blockquote> <p> When you look at the types, that makes sense. After all, there's no guarantee that <code>T</code> is equal to <code>T1</code>. </p> <p> You'll run into similar problems if you mix up the two 'contexts' in other ways. The code doesn't compile. Which is what you want. </p> <h3 id="1075e4f3ff6548cf8806ae9f419910b1"> Conclusion <a href="#1075e4f3ff6548cf8806ae9f419910b1">#</a> </h3> <p> This article demonstrates how to use the <em>Ghosts of Departed Proofs</em> technique in C#. In some ways, I find that it comes across as more idiomatic in C# than in F#. I think this is because rank-2 polymorphism is only possible in F# when using its object-oriented features. Since F# is a functional-first programming language, it seems a little out of place there, whereas it looks more at home in C#. </p> <p> Perhaps I should have designed the F# code to make use of objects to the same degree as I've done here in C#. </p> <p> I think I actually like how the C# API turned out, although having to define and implement a class every time you need to supply a Visitor may feel a bit cumbersome. Even so, <a href="/2024/05/13/gratification">developer experience shouldn't be exclusively about saving a few keystrokes</a>. After all, <a href="/2018/09/17/typing-is-not-a-programming-bottleneck">typing isn't a bottleneck</a>. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/02/03/modelling-data-relationships-with-c-types Dependency inversion without inversion of control https://blog.ploeh.dk/2025/01/27/dependency-inversion-without-inversion-of-control/ Mon, 27 Jan 2025 13:02:00 UTC <div id="post"> <p> <em>Here, have a sandwich.</em> </p> <p> For years I've been thinking about the <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Dependency Inversion Principle</a> (DIP) and <a href="https://en.wikipedia.org/wiki/Inversion_of_control">Inversion of Control</a> (IoC) as two different things. While there's some overlap, they're not the same. To make matters more confusing, most people seem to consider IoC and Dependency Injection (DI) as interchangeable synonyms. As <a href="https://blogs.cuttingedge.it/">Steven van Deursen</a> and I explain in <a href="/dippp">DIPPP</a>, they're not the same. </p> <p> I recently found myself in a discussion on Stack Overflow where I was <a href="https://stackoverflow.com/a/78796558/126014">trying to untangle that confusion</a> for a fellow Stack Overflow user. While I hadn't included a pedagogical Venn diagram, perhaps I should have. </p> <p> <img src="/content/binary/dip-ioc-venn.png" alt="Venn diagram with DIP to the left and IoC to the right. The intersection is substantial, but not overwhelming."> </p> <p> This figure suggests that the sets are of equal size, which doesn't have to be the case. The point, rather, is that while the intersection may be substantial, each <a href="https://en.wikipedia.org/wiki/Complement_(set_theory)">relative complement</a> is not only not empty, but richly populated. </p> <p> In this article, I'm not going to spend more time on the complement IoC without DIP. Rather, I'll expand on how to apply the DIP without IoC. </p> <h3 id="a51dd63df2474002b81bee601c86eb8d"> Appeal to authority? <a href="#a51dd63df2474002b81bee601c86eb8d">#</a> </h3> <p> While writing the Stack Overflow answer, I'd tried to keep citations to 'original sources'. Sometimes, when a problem is technically concrete, it makes sense for me to link to one of my own works, but I've found that when the discussion is more abstract, that rarely helps convincing people. That's understandable. I'd also be sceptical if I were to run into some rando that immediately proceeded to argue a case by linking to his or her own blog. </p> <p> This strategy, however elicited this response: </p> <blockquote> <p> "Are you aware of any DIP-compliant example from Robert Martin that does not utilize polymorphism? The <a href="https://web.archive.org/web/20110714224327/http://www.objectmentor.com/resources/articles/dip.pdf">original paper</a> along with some of Martin's <a href="https://www.youtube.com/watch?v=1XRTvj__ZPY">lectures</a> certainly seem to imply the DIP requires polymorphism." </p> <p> <footer><cite><a href="https://stackoverflow.com/questions/78796242/does-the-dependency-inversion-principle-apply-within-application-layers/78796558#comment138931008_78796558">comment</a>, jaco0646</footer> </blockquote> <p> That's a fair question, and once I started looking for such examples, I had to admit that I couldn't find any. Eventually, I asked <a href="https://en.wikipedia.org/wiki/Robert_C._Martin">Robert C. Martin</a> directly. </p> <blockquote> <p> "Does the DIP require polymorphism? I argue that it does't, but I've managed to entangle myself in a debate where original sources count. Could you help us out?" </p> <footer><cite><a href="https://x.com/ploeh/status/1817141831500542202">Tweet</a>, me</cite></footer> </blockquote> <p> To which he answered in much detail, but of which the essential response was: </p> <blockquote> <p> "The DIP does not require polymorphism. Polymorphism is just one of several mechanisms to achieve dependency inversion." </p> <footer><cite><a href="https://x.com/unclebobmartin/status/1817263979774816379">Tweet</a>, Robert C. Martin</cite></footer> </blockquote> <p> While this was the answer I'd hoped for, it's easy to dismiss this exchange as an <a href="https://en.wikipedia.org/wiki/Argument_from_authority">appeal to authority</a>. On the other hand, as Carl Sagan said, "If you wish to make an apple pie from scratch, you must first invent the universe," which obviously isn't practical, and so we instead <a href="https://en.wikipedia.org/wiki/Standing_on_the_shoulders_of_giants">stand on the shoulders of giants</a>. </p> <p> In this context, asking Robert C. Martin was relevant because he's the original author of works that introduce the DIP. It's reasonable to assume that he has relevant insights on the topic. </p> <p> It's not that I can't argue my case independently, but rather that I didn't think that the comments section of a Stack Overflow question was the right place to do that. This blog, on the other hand, is mine, I can use all the words I'd like, and I'll now proceed to do so. </p> <h3 id="bfe353d609ea45e48ffb0efe939f4c01"> Kernel of the idea <a href="#bfe353d609ea45e48ffb0efe939f4c01">#</a> </h3> <p> All of Robert C. Martin's treatments of the DIP that I've found starts with the general idea and then proceeds to show examples of implementing it in code. As I've already mentioned, I haven't found a text of Martin's where the <em>example</em> doesn't utilize IoC. </p> <p> The central idea, however, says nothing about IoC. </p> <blockquote> <p> "A. High-level modules should not depend on low-level modules. Both should depend on abstractions. </p> <p> "B. Abstractions should not depend on details. Details should depend upon abstractions." </p> <footer><cite><a href="/ref/appp">APPP</a>, Robert C. Martin</cite></footer> </blockquote> <p> While only Martin knows what he actually meant, I can attempt a congenial reading of the work. What is most important here, I think, is that the word <em>abstraction</em> doesn't have to denote a particular kind of language construct, such as an abstract class or interface. Rather, </p> <blockquote> <p> "Abstraction is <em>the elimination of the irrelevant and the amplification of the essential.</em>" </p> <footer><cite><a href="/ref/doocautbm">Designing Object-Oriented C++ Applications Using The Booch Method</a>, ch. 00, Robert C. Martin, his emphasis</cite></footer> </blockquote> <p> The same connotation of <em>abstraction</em> seems to apply to the definition of the DIP. If, for example, we imagine that we consider a Domain Model, the business logic, as the essence we'd like to amplify, we may rightfully consider a particular persistence mechanism a detail. Even more concretely, if you want to take restaurant reservations via a <a href="https://en.wikipedia.org/wiki/REST">REST</a> API, the <a href="/2020/01/27/the-maitre-d-kata">business rules that determine whether or not you can accept a reservation</a> shouldn't depend on a particular database technology. </p> <p> While code examples are useful, there's evidently a risk that if the examples are too much alike, it may constrain readers' thinking. All Martin's examples seem to involve IoC, but for years now, I've mostly been interested in the Dependency Inversion <em>Principle</em> itself. Abstractions should not depend on details. That's the kernel of the idea. </p> <h3 id="cd07b6543fda4612bb0cce38c098cfbc"> IoC isn't functional <a href="#cd07b6543fda4612bb0cce38c098cfbc">#</a> </h3> <p> My thinking was probably helped along by exploring functional programming (FP). A natural question arises when one embarks on learning FP: How does IoC fit with FP? The short answer, it turns out, is that <a href="/2017/01/27/from-dependency-injection-to-dependency-rejection">it doesn't</a>. DI, at least, <a href="/2017/01/30/partial-application-is-dependency-injection">makes everything impure</a>. </p> <p> Does this mean, then, that FP precludes the DIP? That would be a problem, since the notion that abstractions shouldn't depend on details seems important. Doing FP shouldn't entail giving up on important architectural rules. And fortunately, it turns out not being the case. Quite the contrary, a consistent application of <a href="/2018/11/19/functional-architecture-a-definition">functional architecture</a> seems to <a href="/2016/03/18/functional-architecture-is-ports-and-adapters">lead to Ports and Adapters</a>. It'd go against the grain of FP to have a Domain Model query a relational database. Even if abstracted away, a database exists outside the process space of an application, and is inherently impure. IoC doesn't address that concern. </p> <p> In FP, there are other ways to address such problems. </p> <h3 id="53b158bd928e4883992c578be989baf5"> DIP sandwich <a href="#53b158bd928e4883992c578be989baf5">#</a> </h3> <p> While you can always model <a href="/2017/07/10/pure-interactions">pure interactions</a> with free <a href="/2022/03/28/monads">monads</a>, it's usually not necessary. In most cases, an <a href="/2020/03/02/impureim-sandwich">Impureim Sandwich</a> suffices. </p> <p> The sample code base that accompanies <a href="/2021/06/14/new-book-code-that-fits-in-your-head">Code That Fits in Your Head</a> takes a similar approach. While it's <a href="/2024/12/16/a-restaurant-sandwich">possible to refactor it to an explicit Impureim Sandwich</a>, the code presented in the book follows the kindred notion of <a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell">Functional Core, Imperative Shell</a>. </p> <p> The code base implements an online restaurant reservation system, and the Domain Model is a set of data structures and pure functions that operate on them. The central and most complex function is the <code>WillAccept</code> method <a href="/2020/11/30/name-by-role">shown here</a>. It decides whether to accept a reservation request, based on restaurant table configurations, existing reservations, business rules related to seating durations, etc. It does this without depending on details. It doesn't know about databases, the application's configuration system, or how to send emails in case it decides to accept a reservation. </p> <p> All of this is handled by the application's HTTP Model, using the demarcation shown in <a href="/2023/09/04/decomposing-ctfiyhs-sample-code-base">Decomposing CTFiYH's sample code base</a>. The HTTP Model defines Controllers, <a href="https://en.wikipedia.org/wiki/Data_transfer_object">Data Transfer Objects</a> (DTOs), middleware, and other building blocks required to drive the actual REST API. </p> <p> The <code>ReservationsController</code> class contains, among many other methods, this helper method that illustrates the point: </p> <p> <pre><span style="color:blue;">private</span>&nbsp;<span style="color:blue;">async</span>&nbsp;Task&lt;ActionResult&gt;&nbsp;<span style="font-weight:bold;color:#74531f;">TryCreate</span>(Restaurant&nbsp;<span style="font-weight:bold;color:#1f377f;">restaurant</span>,&nbsp;Reservation&nbsp;<span style="font-weight:bold;color:#1f377f;">reservation</span>) { &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">using</span>&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">scope</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;TransactionScope(TransactionScopeAsyncFlowOption.Enabled); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">reservations</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;Repository.ReadReservations(restaurant.Id,&nbsp;reservation.At); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">now</span>&nbsp;=&nbsp;Clock.GetCurrentDateTime(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">if</span>&nbsp;(!restaurant.MaitreD.WillAccept(now,&nbsp;reservations,&nbsp;reservation)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;NoTables500InternalServerError(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">await</span>&nbsp;Repository.Create(restaurant.Id,&nbsp;reservation); &nbsp;&nbsp;&nbsp;&nbsp;scope.Complete(); &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;Reservation201Created(restaurant.Id,&nbsp;reservation); }</pre> </p> <p> Notice the call to <code>restaurant.MaitreD.WillAccept</code>. The Controller gathers all data required to call the <a href="https://en.wikipedia.org/wiki/Pure_function">pure function</a> and subsequently acts on the return value. This keeps the abstraction (<code>MaitreD</code>) free of implementation details. </p> <h3 id="cb60ef67d81e4754b959ff93d213ed80"> DI addressing another concern <a href="#cb60ef67d81e4754b959ff93d213ed80">#</a> </h3> <p> You may be wondering what exactly <code>Repository</code> is. If you've bought the book, you also have access to the sample code base, in which case you'd be able to look it up. It turns out that it's an injected dependency. While this may seem a bit contradictory, it also gives me the opportunity to discuss that this isn't an all-or-nothing proposition. </p> <p> Consider the architecture diagram from <a href="/2023/09/04/decomposing-ctfiyhs-sample-code-base">Decomposing CTFiYH's sample code base</a>, repeated here for convenience: </p> <p> <img src="/content/binary/ctfiyh-decomposed-architecture.png" alt="Ports-and-adapters architecture diagram."> </p> <p> In the context of this diagram, the DIP is being applied in two different ways. From the outer Web Host to the HTTP Model, the decomposed code base uses ordinary DI. From the HTTP Model to the Domain Model, there's no inversion of control, but rather the important essence of the DIP: That the Domain Model doesn't depend on any of the details that surrounds it. Even so, the dependencies remain inverted, as indicated by the arrows. </p> <p> What little DI that's left remains to support automated testing. Injecting <code>Repository</code> and a few other <a href="https://stackoverflow.blog/2022/01/03/favor-real-dependencies-for-unit-testing/">real dependencies</a> enabled me to test-drive the externally visible behaviour of the system with <a href="/2019/02/18/from-interaction-based-to-state-based-testing">state-based</a> <a href="/2021/01/25/self-hosted-integration-tests-in-aspnet">self-hosted tests</a>. </p> <p> If I hadn't cared about that, I could have hard-coded the <code>SqlReservationsRepository</code> object directly into the Controller and merged the Web Host with the HTTP Module. The Web Host is quite minimal anyway. This would, of course, have meant that the DIP no longer applied at that level, but even so, the interaction between the HTTP Model and the Domain Model would still follow the principle. </p> <p> One important point about the above figure is that it's not to scale. The Web Host is in reality just six small classes, and the SQL and SMTP libraries each only contain a single class. </p> <h3 id="4f8fe34378a34bf4b3a6ebe9188c8d9b"> Conclusion <a href="#4f8fe34378a34bf4b3a6ebe9188c8d9b">#</a> </h3> <p> Despite the name similarity, the Dependency Inversion Principle isn't equivalent with Inversion of Control or Dependency Injection. There's a sizeable intersection between the two, but the DIP doesn't <em>require</em> IoC. </p> <p> I often use the Functional Core, Imperative Shell architecture, or the Impureim Sandwich pattern to invert the dependencies without inverting control. This keeps most of my code more functional, which also means that it <a href="/2021/07/28/referential-transparency-fits-in-your-head">fits better in my head</a> and is <a href="/2015/05/07/functional-design-is-intrinsically-testable">intrinsically testable</a>. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/01/27/dependency-inversion-without-inversion-of-control Modelling data relationships with F# types https://blog.ploeh.dk/2025/01/20/modelling-data-relationships-with-f-types/ Mon, 20 Jan 2025 07:24:00 UTC <div id="post"> <p> <em>An F# example implementation of Ghosts of Departed Proofs.</em> </p> <p> In a previous article, <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a>, I used a code example to discuss how to communicate an API's contract to client developers; that is, users of the API. In the article, I wrote </p> <blockquote> <p> "All this said, however, it's also possible that I'm missing an obvious design alternative. If you can think of a way to model this relationship in a non-<a href="https://www.hillelwayne.com/post/constructive/">predicative</a> way, please <a href="https://github.com/ploeh/ploeh.github.com?tab=readme-ov-file#comments">write a comment</a>." </p> </blockquote> <p> And indeed, a reader helpfully offered an alternative: </p> <blockquote> <p> "Regarding the relation between the array and the index, you will find the paper called "Ghosts of departed proofs" interesting. Maybe an overkill in this case, maybe not, but a very interesting and useful technique in general." </p> <footer><cite><a href="https://x.com/Savlambda/status/1876227452886012014">borar</a></cite></footer> </blockquote> <p> I wouldn't call it 'an <em>obvious</em> design alternative', but nonetheless find it interesting. In this article, I'll pick up the code from <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a> and show how the 'Ghosts of Departed Proofs' (GDP) technique may be applied. </p> <h3 id="c43d4e8c8e414b46bf65817e7b00e85e"> Problem review <a href="#c43d4e8c8e414b46bf65817e7b00e85e">#</a> </h3> <p> Before we start with the GDP technique, a brief review of the problem is in order. For the complete overview, you should read the <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a> article. In the present article, however, we'll focus on one particular problem related to <a href="/2022/10/24/encapsulation-in-functional-programming">encapsulation</a>: </p> <p> Ideally, the <code>cut</code> function should take two input arguments. The first argument, <code>p</code>, is an array or list of prices. The second argument, <code>n</code>, is the size of a rod to cut optimally. One precondition states that <code>n</code> must be less than or equal to the length of <code>p</code>. This is because the algorithm needs to look up the price of a rod of size <code>n</code>, and it can't do that if <code>n</code> is greater than the length of <code>p</code>. The implied relationship is that <code>p</code> is indexed by rod size, so that if you want to find the price of a rod of size <code>n</code>, you look at the nth element in <code>p</code>. </p> <p> How may we model such a relationship in a way that protects the precondition? </p> <p> An obvious choice, particularly in object-oriented design, is to use a <a href="https://en.wikipedia.org/wiki/Guard_(computer_science)">Guard Clause</a>. In the <a href="https://fsharp.org/">F#</a> code base, it might look like this: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">cut</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;:&nbsp;_&nbsp;<span style="color:#2b91af;">array</span>)&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>.Length&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">then</span>&nbsp;<span style="color:blue;">raise</span>&nbsp;(<span style="color:#2b91af;">ArgumentOutOfRangeException</span>&nbsp;<span style="color:#a31515;">&quot;n&nbsp;must&nbsp;be&nbsp;less&nbsp;than&nbsp;the&nbsp;length&nbsp;of&nbsp;p&quot;</span>) &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;The&nbsp;rest&nbsp;of&nbsp;the&nbsp;function&nbsp;body...</span></pre> </p> <p> You might argue that in F# and other functional programming languages, throwing exceptions isn't <a href="/2015/08/03/idiomatic-or-idiosyncratic">idiomatic</a>. Instead, you ought to return <code>Result</code> or <code>Option</code> values, here the latter: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">cut</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;:&nbsp;_&nbsp;<span style="color:#2b91af;">array</span>)&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>.Length&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">then</span>&nbsp;<span style="color:#2b91af;">None</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;The&nbsp;rest&nbsp;of&nbsp;the&nbsp;function&nbsp;body...</span></pre> </p> <p> To be clear, in most code bases, this is exactly what I would do. What follows is rather exotic, and hardly suitable for all use cases. </p> <h3 id="9457df27904b4b9ea65b4713dea20fbd"> Proofs as values <a href="#9457df27904b4b9ea65b4713dea20fbd">#</a> </h3> <p> It's not too hard to model the lower boundary of the <code>n</code> parameter. As is often the case, it turns out that the number must be a natural number. I already covered that in the <a href="/2025/01/06/encapsulating-rod-cutting">previous article</a>. It's much harder, however, to model the upper boundary of the value, because it depends on the size of <code>p</code>. </p> <p> The following is based on the paper <a href="https://dl.acm.org/doi/10.1145/3242744.3242755">Ghosts of Departed Proofs</a>, as well as <a href="https://gist.github.com/Savelenko/9f21c63fdc00b52a64739122176b7453">a helpful Gist</a> also provided by Borar. (The link to the paper is to what I believe is the 'official' page for it, and since it's part of the ACM digital library, it's behind a paywall. Even so, as is the case with most academic papers, it's easy enough to find a PDF of it somewhere else. Not that I endorse content piracy, but it's my impression that academic papers are usually disseminated by the authors themselves.) </p> <p> The idea is to enable a library to issue a 'proof' about a certain condition. In the example I'm going to use here, the proof is that a certain number is in the valid range for a given list of prices. </p> <p> We actually can't entirely escape the need for a run-time check, but we do gain two other benefits. The first is that we're now using the type system to communicate a relationship that otherwise would have to be described in written documentation. The second is that once the proof has been issued, there's no need to perform additional run-time checks. </p> <p> This can help move an API towards a more total, as opposed to <a href="https://en.wikipedia.org/wiki/Partial_function">partial</a>, definition, which again moves towards what Michael Feathers calls <a href="https://youtu.be/AnZ0uTOerUI?si=1gJXYFoVlNTSbjEt">unconditional code</a>. This is particularly useful if the alternative is an API that 'forgets' which run-time guarantees have already been checked. The paper has some examples. I've also recently encountered similar situations when doing <a href="https://adventofcode.com/2024">Advent of Code 2024</a>. Many days my solution involved immutable maps (like hash tables) that I'd recurse over. In many cases I'd write an algorithm where I with absolute certainty knew that a particular key was in the map (if, for example, I'd just put it there three lines earlier). In such cases, you don't want a total function that returns an option or <a href="/2022/04/25/the-maybe-monad">Maybe</a> value. You want a partial function. Or a type-level guarantee that the value is, indeed, in the map. </p> <p> For the example in this article, it's overkill, so you may wonder what the point is. On the other hand, a simple example makes it easier to follow what's going on. Hopefully, once you understand the technique, you can extrapolate it to situations where it might be more warranted. </p> <h3 id="46bc8e47a37f43b3b126946ac29239b0"> Proof contexts <a href="#46bc8e47a37f43b3b126946ac29239b0">#</a> </h3> <p> The overall idea should look familiar to practitioners of statically-typed functional programming. Instead of plain functions and data structures, we introduce a special 'context' in which we have to run our computations. This is similar to how <a href="/2023/01/09/the-io-monad">the IO monad</a> works, or, in fact, most monads. You're not supposed to <a href="/2019/02/04/how-to-get-the-value-out-of-the-monad">get the value out of the monad</a>. Rather, you should inject the desired behaviour <em>into</em> the monad. </p> <p> We find a similar design with existential types, or with the <a href="https://hackage.haskell.org/package/base/docs/Control-Monad-ST.html">ST monad</a>, on which the ideas in the GDP paper are acknowledged to be based. We even see a mutation-based variation in the article <a href="/2024/06/24/a-mutable-priority-collection">A mutable priority collection</a>, where we may think of the <code>Edit</code> API as a variation of the ST monad, since it allows 'localized' state mutation. </p> <p> I'll attempt to illustrate it like this: </p> <p> <img src="/content/binary/library-with-computation-context.png" alt="A box labelled 'library' with a 'sandbox' area inside. To its left, another box labelled 'Client code' with an arrow to the library box, as well as an arrow to a box inside the sandbox area labelled 'Client computation'."> </p> <p> A library offers a set of functions and data structures for immediate use. In addition, it also provides a <a href="https://en.wikipedia.org/wiki/Higher-order_function">higher-oder function</a> that enables client code to embed a computation into a special 'sandbox' area where special rules apply. The paper calls such a context a 'name', which it does because it's trying to be as general as possible. As I'm writing this, I find it easier to think of this 'sandbox' as a 'proof context'. It's a context in which proof values exist. Crucially, as we shall see, they don't exist outside of this context. </p> <h3 id="50d1ba9968d04529be3cbccfd6b05061"> Size proofs <a href="#50d1ba9968d04529be3cbccfd6b05061">#</a> </h3> <p> In the rod-cutting example, we particularly care about proving that a given number <code>n</code> is within the size of the price list. We do this by representing the proof as a value: </p> <p> <pre><span style="color:blue;">type</span>&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;=&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:#2b91af;">Size</span>&nbsp;<span style="color:blue;">of</span>&nbsp;<span style="color:#2b91af;">int</span>&nbsp;<span style="color:blue;">with</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>.Value&nbsp;=&nbsp;<span style="color:blue;">let</span>&nbsp;(<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">override</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>.<span style="font-weight:bold;color:#74531f;">ToString</span>&nbsp;()&nbsp;=&nbsp;<span style="color:blue;">let</span>&nbsp;(<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="color:#74531f;">string</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span></pre> </p> <p> Two things are special about this type definition: </p> <ul> <li>The constructor is <code>private</code>.</li> <li>It has a phantom type <code>'a</code>.</li> </ul> <p> A phantom type is a generic type parameter that has no run-time value. Notice that <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> contains no value of the type <code>'a</code>. The type only exists at compile-time. </p> <p> You can think of the type parameter as similar to a security token. The issuer of the proof associates a particular security token to vouch for its validity. Usually, when we talk about security tokens, they do have a run-time representation (typically a byte array) because we need to exchange them with other processes. This is, for example, how claims-based authentication works. </p> <p> <img src="/content/binary/claim-with-certificate.png" alt="A box labelled 'claim'. The box has a ribboned seal in the lower right corner." width="200"> </p> <p> In this case, our concern isn't security. Rather, we wish to communicate and enforce certain relationships. Since we wish to leverage the type system, we use a type as a token. </p> <p> <img src="/content/binary/size-with-phantom-type.png" alt="A box labelled 'size'. The box has another label in the lower right corner with the generic type argument 'a." width="200"> </p> <p> Since the <code>Size</code> constructor is <code>private</code>, the library controls how it issues proofs, a bit like a claims issuer can sign a claim with its private key. </p> <p> Okay, but how are <code>Size</code> proofs issued? </p> <h3 id="28af8638928c4327b0c3a43d6c36711f"> Issuing size proofs <a href="#28af8638928c4327b0c3a43d6c36711f">#</a> </h3> <p> As you'll see later, more than one API may issue <code>Size</code> proofs, but the most fundamental is that you can query a price list for such a proof: </p> <p> <pre><span style="color:blue;">type</span>&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;=&nbsp;<span style="color:blue;">private</span>&nbsp;<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="color:blue;">of</span>&nbsp;<span style="color:#2b91af;">int</span>&nbsp;<span style="color:#2b91af;">list</span>&nbsp;<span style="color:blue;">with</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>.Length&nbsp;=&nbsp;<span style="color:blue;">let</span>&nbsp;(<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>)&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>&nbsp;<span style="color:blue;">in</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>.Length &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>.<span style="font-weight:bold;color:#74531f;">trySize</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;:&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;<span style="color:#2b91af;">option</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;0&nbsp;&lt;&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;&amp;&amp;&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>&nbsp;&lt;=&nbsp;<span style="font-weight:bold;color:#1f377f;">this</span>.Length &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">then</span>&nbsp;<span style="color:#2b91af;">Some</span>&nbsp;(<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">candidate</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">else</span>&nbsp;<span style="color:#2b91af;">None</span></pre> </p> <p> The <code>trySize</code> member function issues a <code><span style="color:#2b91af;">Some</span> <span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> value if the <code>candidate</code> is within the size of the price array. As discussed above, we can't completely avoid a run-time check, but now that we have the proof, we don't need to <em>repeat</em> that run-time check if we wanted to use a particular <code>Size</code> value with the same <code>PriceList</code>. </p> <p> Notice how immutability is an essential part of this design. If, in the object-oriented manner, we allow a price list to change, we could make it shorter. This could invalidate some proof that we previously issued. Since, however, the price list is immutable, we can trust that once we've checked a size, it remains valid. You can also think of this as a sort of <a href="/encapsulation-and-solid">encapsulation</a>, in the sense that once we've assured ourselves that an object, or here rather a value, is valid, it remains valid. Indeed, <a href="/2024/06/12/simpler-encapsulation-with-immutability">encapsulation is simpler with immutability</a>. </p> <p> You probably still have some questions. For instance, how do we ensure that a size proof issued by one price list can't be used against another price list? Imagine that you have two price lists. One has ten prices, the other twenty. You could have the larger one issue a proof that <em>size 17</em> is valid. What prevents you from using that proof with the smaller price list? </p> <p> That's the job of that phantom type. Notice how a <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> issues a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> proof. It's the same generic type argument. </p> <p> Usually, I <a href="/2024/11/04/pendulum-swing-no-haskell-type-annotation-by-default">extol F#'s type inference</a>. I prefer not having to use type annotations unless I have to. When it comes to GDP, however, type annotations are necessary, because we need these phantom types to line up. Without the type annotations, they wouldn't do that. </p> <p> In the above example, the smaller price list might have the type <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> and the larger one the type <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;b</span>&gt;</code>. The smaller would issue proofs of the type <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code>, and the larger one proofs of the type <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;b</span>&gt;</code>. As you'll see, you can't use a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> where a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;b</span>&gt;</code> is required, or vice versa. </p> <p> You may still wonder how one then creates <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> values. After all, that type also has a <code>private</code> constructor. </p> <p> We'll get back to that later. </p> <h3 id="193350b5b4ab4327b021ac42403dab11"> Proof-based cut API <a href="#193350b5b4ab4327b021ac42403dab11">#</a> </h3> <p> Before we look at how client code may consume APIs based on proofs such as <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code>, we should review their expressive power. What does this design enable us to say? </p> <p> While the first example above, with the Guard Clause alternative, was based on the initial imperative implementation shown in the article <a href="/2024/12/23/implementing-rod-cutting">Implementing rod-cutting</a>, the rest of the present article builds on the refactored code from <a href="/2025/01/06/encapsulating-rod-cutting">Encapsulating rod-cutting</a>. </p> <p> The first change I need to introduce is to the <code>Cut</code> record type: </p> <p> <pre><span style="color:blue;">type</span>&nbsp;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;=&nbsp;{&nbsp;Revenue&nbsp;:&nbsp;<span style="color:#2b91af;">int</span>;&nbsp;Size&nbsp;:&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;}</pre> </p> <p> Notice that I've changed the type of the <code>Size</code> property to <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code>. This has the implication that <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> now also has a phantom type, and since client code can't create <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> values, by transitivity it means that neither can client code create <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> values. These values can only be issued as proofs. </p> <p> This enables us to change the type definition of the <code>cut</code> function: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">cut</span>&nbsp;(<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;:&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;)&nbsp;(<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;:&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;)&nbsp;:&nbsp;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;<span style="color:#2b91af;">list</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Implementation&nbsp;follows&nbsp;here...</span></pre> </p> <p> Notice how all the phantom types line up. In order to call the function, client code must supply a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> value issued by a compatible <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> value. Upon a valid call, the function returns a list of <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> values. </p> <p> Pay attention to what is being communicated. You may find this strange and impenetrable, but for a reader who understands GDP, much about the contract is communicated through the types. We can see that <code>n</code> relates to <code>prices</code>, because the 'proof token' (the generic type parameter <code>'a</code>) is the same for both arguments. A reader who understands how <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> proofs are issued will now understand what the preconditions is: The <code>n</code> argument must be valid according to the size of the <code>prices</code> argument. </p> <p> The type of the <code>cut</code> function also communicates a postcondition: It guarantees that the <code>Size</code> values of each <code><span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> returned is valid according to the supplied <code>prices</code>. In other words, it means that no <a href="/2013/07/08/defensive-coding">defensive coding</a> is necessary. Client code doesn't have to check whether or not the price of each indicated cut can actually be found in <code>prices</code>. The types guarantee that they can. </p> <p> You may consider the <code>cut</code> function a 'secondary' issuer of <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> proofs, since it returns such values. If you wanted to call <code>cut</code> again with one of those values, you could. </p> <p> Compared to the previous article, I don't think I changed much else in the <code>cut</code> function, besides the initial function declaration, and the last line of code, but for good measure, here's the entire function: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">cut</span>&nbsp;(<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;:&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;)&nbsp;(<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;:&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;)&nbsp;:&nbsp;<span style="color:#2b91af;">Cut</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;<span style="color:#2b91af;">list</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:green;">//&nbsp;Implementation&nbsp;follows&nbsp;here...</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;=&nbsp;0&nbsp;<span style="color:#2b91af;">::</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">Array</span>.<span style="color:#74531f;">ofList</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">findBestCut</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[1..<span style="font-weight:bold;color:#1f377f;">j</span>] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">map</span>&nbsp;(<span style="color:blue;">fun</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>[<span style="font-weight:bold;color:#1f377f;">i</span>]&nbsp;+&nbsp;<span style="color:#2b91af;">Map</span>.<span style="color:#74531f;">find</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;-&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">maxBy</span>&nbsp;<span style="color:#74531f;">fst</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">aggregate</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">acc</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span>&nbsp;=&nbsp;<span style="color:#74531f;">snd</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">acc</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">q</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;=&nbsp;<span style="color:#74531f;">findBestCut</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">j</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">cuts</span>&nbsp;=&nbsp;<span style="color:#74531f;">fst</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">acc</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#74531f;">cuts</span>&nbsp;&lt;&lt;&nbsp;(<span style="color:#74531f;">cons</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">q</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)),&nbsp;<span style="color:#2b91af;">Map</span>.<span style="color:#74531f;">add</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span>.Count&nbsp;<span style="font-weight:bold;color:#1f377f;">q</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">revenues</span> &nbsp;&nbsp;&nbsp;&nbsp;[1..<span style="font-weight:bold;color:#1f377f;">n</span>] &nbsp;&nbsp;&nbsp;&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">fold</span>&nbsp;<span style="color:#74531f;">aggregate</span>&nbsp;(<span style="color:#74531f;">id</span>,&nbsp;<span style="color:#2b91af;">Map</span>.<span style="color:#74531f;">add</span>&nbsp;0&nbsp;0&nbsp;<span style="color:#2b91af;">Map</span>.empty) &nbsp;&nbsp;&nbsp;&nbsp;|&gt;&nbsp;<span style="color:#74531f;">fst</span>&nbsp;&lt;|&nbsp;[]&nbsp;<span style="color:green;">//&nbsp;Evaluate&nbsp;Hughes&nbsp;list</span> &nbsp;&nbsp;&nbsp;&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">map</span>&nbsp;(<span style="color:blue;">fun</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">r</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>)&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;{&nbsp;Revenue&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>;&nbsp;Size&nbsp;=&nbsp;<span style="color:#2b91af;">Size</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">i</span>&nbsp;})</pre> </p> <p> The <code>cut</code> function is part of the same module as <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code>, so even though the constructor is <code>private</code>, the <code>cut</code> function can still use it. </p> <p> Thus, the entire proof mechanism is for external use. Internally, the library code may take shortcuts, so it's up to the library author to convince him- or herself that the contract holds. In this case, I'm quite confident that the function only issues valid proofs. After all, I've lifted the algorithm from <a href="/ref/clrs">an acclaimed text book</a>, and this particular implementation is covered by more than 10,000 test cases. </p> <h3 id="dcbcbee557a54a8aaa701484ad89e90f"> Proof-based solve API <a href="#dcbcbee557a54a8aaa701484ad89e90f">#</a> </h3> <p> The <code>solve</code> code hasn't changed, I believe: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">solve</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;=&nbsp;<span style="color:#74531f;">cut</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span> &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="color:blue;">rec</span>&nbsp;<span style="color:#74531f;">imp</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">if</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;&lt;=&nbsp;0&nbsp;<span style="color:blue;">then</span>&nbsp;[]&nbsp;<span style="color:blue;">else</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">idx</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;-&nbsp;1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>[<span style="font-weight:bold;color:#1f377f;">idx</span>].Size &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>&nbsp;<span style="color:#2b91af;">::</span>&nbsp;<span style="color:#74531f;">imp</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;-&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>.Value) &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#74531f;">imp</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>.Value</pre> </p> <p> While the code hasn't changed, the type has. In this case, no explicit type annotations are necessary, because the types are already correctly inferred from the use of <code>cut</code>: </p> <p> <pre>solve:&nbsp;prices:&nbsp;PriceList&lt;&#39;a&gt;&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;n:&nbsp;Size&lt;&#39;a&gt;&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;Size&lt;&#39;a&gt;&nbsp;list</pre> </p> <p> Again, the phantom types line up as desired. </p> <h3 id="f2e9d4cab42b4d74bb472c3aee2e45ef"> Proof-based revenue calculation <a href="#f2e9d4cab42b4d74bb472c3aee2e45ef">#</a> </h3> <p> Although I didn't show it in the previous article, I also included a function to calculate the revenue from a list of cuts. It gets the same treatment as the other functions: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">calculateRevenue</span>&nbsp;(<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>&nbsp;:&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;)&nbsp;(<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;:&nbsp;<span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;<span style="color:#2b91af;">list</span>)&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">sumBy</span>&nbsp;(<span style="color:blue;">fun</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">s</span>&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">prices</span>[<span style="font-weight:bold;color:#1f377f;">s</span>.Value&nbsp;-&nbsp;1])</pre> </p> <p> Again we see how the GDP-based API communicates a precondition: The <code>cuts</code> must be valid according to the <code>prices</code>; that is, each cut, indicated by its <code>Size</code> property, must be guaranteed to be within the range defined by the price list. This makes the function total; or, unconditional code, as Michael Feathers would put it. The function can't fail at run time. </p> <p> (I am, once more, deliberately ignoring the entirely independent problem of potential integer overflows.) </p> <p> While you could repeatedly call <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;.<span style="font-weight:bold;color:#74531f;">trySize</span></code> to produce a list of cuts, the most natural way to produce such a list of cuts is to first call <code>cut</code>, and then pass its result to <code>calculateRevenue</code>. </p> <p> The function returns <code>int</code>. </p> <h3 id="0a22569816ad4b179a365d2dc3ad81f4"> Proof-based printing <a href="#0a22569816ad4b179a365d2dc3ad81f4">#</a> </h3> <p> Finally, here's <code>printSolution</code>: </p> <p> <pre><span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">printSolution</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;=&nbsp;<span style="color:#74531f;">solve</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">iter</span>&nbsp;(<span style="color:#74531f;">printfn</span>&nbsp;<span style="color:#a31515;">&quot;</span><span style="color:#2b91af;">%O</span><span style="color:#a31515;">&quot;</span>)</pre> </p> <p> It hasn't changed much since the previous incarnation, but the type is now <code>PriceList&lt;&#39;a&gt;&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;Size&lt;&#39;a&gt;&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;unit</code>. Again, the precondition is the same as for <code>cut</code>. </p> <h3 id="2216067c41c44ade8855e4c6f8216d6d"> Running client code <a href="#2216067c41c44ade8855e4c6f8216d6d">#</a> </h3> <p> How in the world do you write client code against this API? After all, the types all have <code>private</code> constructors, so we can't create any values. </p> <p> If you trace the code dependencies, you'll notice that <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> sits at the heart of the API. If you have a <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code>, you'd be able to produce the other values, too. </p> <p> So how do you create a <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> value? </p> <p> You don't. You call the following <code>runPrices</code> function, and give it a <code>PriceListRunner</code> that it'll embed and run in the 'sandbox' illustrated above. </p> <p> <pre><span style="color:blue;">type</span>&nbsp;<span style="color:#2b91af;">PriceListRunner</span>&lt;<span style="color:#2b91af;">&#39;r</span>&gt;&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">abstract</span>&nbsp;<span style="font-weight:bold;color:#74531f;">Run</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;:&nbsp;<span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;<span style="color:#2b91af;">&#39;r</span> <span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">runPrices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">ctx</span>&nbsp;:&nbsp;<span style="color:#2b91af;">PriceListRunner</span>&lt;<span style="color:#2b91af;">&#39;r</span>&gt;)&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">ctx</span>.<span style="font-weight:bold;color:#74531f;">Run</span>&nbsp;(<span style="color:#2b91af;">PriceList</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl</span>)</pre> </p> <p> As the paper describes, the GDP trick hinges on rank-2 polymorphism, and the only way (that I know of) this is supported in F# is on methods. An object is therefore required, and we define the abstract <code><span style="color:#2b91af;">PriceListRunner</span>&lt;<span style="color:#2b91af;">&#39;r</span>&gt;</code> class for that purpose. </p> <p> Client code must implement the abstract class to call the <code>runPrices</code> function. Fortunately, since F# has <a href="https://learn.microsoft.com/dotnet/fsharp/language-reference/object-expressions">object expressions</a>, client code might look like this: </p> <p> <pre>[&lt;<span style="color:#2b91af;">Fact</span>&gt;] <span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">``CLRS&nbsp;example``</span>&nbsp;()&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;=&nbsp;[1;&nbsp;5;&nbsp;8;&nbsp;9;&nbsp;10;&nbsp;17;&nbsp;17;&nbsp;20;&nbsp;24;&nbsp;30] &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">runPrices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p</span>&nbsp;{&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PriceListRunner</span>&lt;_&gt;&nbsp;<span style="color:blue;">with</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;__.<span style="font-weight:bold;color:#74531f;">Run</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl</span>&nbsp;=&nbsp;<span style="color:blue;">option</span>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let!</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">pl</span>.<span style="font-weight:bold;color:#74531f;">trySize</span>&nbsp;10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">cut</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:#2b91af;">List</span>.<span style="color:#74531f;">map</span>&nbsp;(<span style="color:blue;">fun</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">c</span>&nbsp;<span style="color:blue;">-&gt;</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">c</span>.Revenue,&nbsp;<span style="font-weight:bold;color:#1f377f;">c</span>.Size.Value))&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts</span>&nbsp;}&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;1,&nbsp;&nbsp;1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;5,&nbsp;&nbsp;2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(&nbsp;8,&nbsp;&nbsp;3) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(10,&nbsp;&nbsp;2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(13,&nbsp;&nbsp;2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(17,&nbsp;&nbsp;6) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(18,&nbsp;&nbsp;1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(22,&nbsp;&nbsp;2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(25,&nbsp;&nbsp;3) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(30,&nbsp;10) &nbsp;&nbsp;&nbsp;&nbsp;]&nbsp;|&gt;&nbsp;<span style="color:#2b91af;">Some</span>&nbsp;=!&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span></pre> </p> <p> This is an <a href="https://xunit.net/">xUnit.net</a> test where <code>actual</code> is produced by <code>runPrices</code> and an object expression that defines the code to run in the proof context. When the <code>Run</code> method runs, it runs with a concrete type that the compiler picked for <code>'a</code>. This type is only in scope within that method, and can't escape it. </p> <p> The implementing class is given a <code><span style="color:#2b91af;">PriceList</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> as an input argument. In this example, it tries to create a size of 10, which succeeds because the price list has ten elements. </p> <p> Notice that the <code>Run</code> method transforms the <code>cuts</code> to tuples. Why doesn't it return <code>cuts</code> directly? </p> <p> It can't. It's part of the deal. If I change the last line of <code>Run</code> to <code>return cuts</code>, the code no longer compiles. The compiler error is: </p> <blockquote> <p> This code is not sufficiently generic. The type variable 'a could not be generalized because it would escape its scope. </p> </blockquote> <p> Remember I wrote that <code>'a</code> can't escape the scope of <code>Run</code>? This is enforced by the type system. </p> <h3 id="6583d683c77c4bfba53f3f2c1195603e"> Preventing misalignment <a href="#6583d683c77c4bfba53f3f2c1195603e">#</a> </h3> <p> You may already consider it a benefit that this kind of API design uses the type system to communicate pre- and postconditions. Perhaps you also wonder how it prevents errors. As already discussed, if you're dealing with multiple price lists, it shouldn't be possible to use a size proof issued by one, with another. Let's see how that might look. We'll start with a correctly coded unit test: </p> <p> <pre>[&lt;<span style="color:#2b91af;">Fact</span>&gt;] <span style="color:blue;">let</span>&nbsp;<span style="color:#74531f;">``Nest&nbsp;two&nbsp;solutions``</span>&nbsp;()&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p1</span>&nbsp;=&nbsp;[1;&nbsp;2;&nbsp;2] &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p2</span>&nbsp;=&nbsp;[1] &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">runPrices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p1</span>&nbsp;{&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PriceListRunner</span>&lt;_&gt;&nbsp;<span style="color:blue;">with</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;__.<span style="font-weight:bold;color:#74531f;">Run</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl1</span>&nbsp;=&nbsp;<span style="color:blue;">option</span>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let!</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n1</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">pl1</span>.<span style="font-weight:bold;color:#74531f;">trySize</span>&nbsp;3 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts1</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">solve</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl1</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n1</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">r</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">calculateRevenue</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl1</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts1</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let!</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">inner</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">runPrices</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">p2</span>&nbsp;{&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">PriceListRunner</span>&lt;_&gt;&nbsp;<span style="color:blue;">with</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">member</span>&nbsp;__.<span style="font-weight:bold;color:#74531f;">Run</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl2</span>&nbsp;=&nbsp;<span style="color:blue;">option</span>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let!</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n2</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">pl2</span>.<span style="font-weight:bold;color:#74531f;">trySize</span>&nbsp;1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts2</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">solve</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl2</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n2</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">calculateRevenue</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl2</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts2</span>&nbsp;}&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">return</span>&nbsp;(<span style="font-weight:bold;color:#1f377f;">r</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">inner</span>)&nbsp;}&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#2b91af;">Some</span>&nbsp;(3,&nbsp;1)&nbsp;=!&nbsp;<span style="font-weight:bold;color:#1f377f;">actual</span></pre> </p> <p> This code compiles because I haven't mixed up the <code>Size</code> or <code>Cut</code> values. What happens if I 'accidentally' change the 'inner' <code>Rod.solve</code> call to <code><span style="color:blue;">let</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">cuts2</span>&nbsp;=&nbsp;<span style="color:#2b91af;">Rod</span>.<span style="color:#74531f;">solve</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">pl2</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">n1</span></code>? </p> <p> The code doesn't compile: </p> <blockquote> <p> Type mismatch. Expecting a 'Size&lt;'a&gt;' but given a 'Size&lt;'b&gt;' The type ''a' does not match the type ''b' </p> </blockquote> <p> This is fortunate, because <code>n1</code> wouldn't work with <code>pl2</code>. Consider that <code>n1</code> contains the number <code>3</code>, which is valid for the larger list <code>pl1</code>, but not the shorter list <code>pl2</code>. </p> <p> Proofs are issued with a particular generic type argument - the type-level 'token', if you will. It's possible for a library API to explicitly propagate such proofs; you see a hint of that in <code>cut</code>, which not only takes as input a <code><span style="color:#2b91af;">Size</span>&lt;<span style="color:#2b91af;">&#39;a</span>&gt;</code> value, but also issues new proofs as a result. </p> <p> At the same time, this design prevents proofs from being mixed up. Each set of proofs belongs to a particular proof context. </p> <p> You get the same compiler error if you accidentally mix up some of the other terms. </p> <h3 id="d143cd141fc143c49e14d8e600492dc0"> Conclusion <a href="#d143cd141fc143c49e14d8e600492dc0">#</a> </h3> <p> One goal in the GDP paper is to introduce a type-safe API design that's also <em>ergonomic</em>. Matt Noonan, the author, defines <em>ergonomic</em> as a design where correct use of the API doesn't place an undue burden on the client developer. The paper's example language is <a href="https://www.haskell.org/">Haskell</a> where <a href="https://wiki.haskell.org/Rank-N_types">rank-2 polymorphism</a> has a low impact on the user. </p> <p> F# only supports rank-2 polymorphism in method definitions, which makes consuming a GDP API more awkward than in Haskell. The need to create a new type, and the few lines of boilerplate that entails, is a drawback. </p> <p> Even so, the GDP trick is a nice addition to your functional tool belt. You'll hardly need it every day, but I personally like having some specialized tools lying around together with the everyday ones. </p> <p> But wait! The reason that F# has support for rank-2 polymorphism through object methods is because C# has that language feature. This must mean that the GDP technique works in C# as well, doesn't it? Indeed it does. </p> <p> <strong>Next:</strong> <a href="/2025/02/03/modelling-data-relationships-with-c-types">Modelling data relationships with C# types</a>. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/01/20/modelling-data-relationships-with-f-types Recawr Sandwich https://blog.ploeh.dk/2025/01/13/recawr-sandwich/ Mon, 13 Jan 2025 15:52:00 UTC <div id="post"> <p> <em>A pattern variation.</em> </p> <p> After writing the articles <a href="/2024/11/18/collecting-and-handling-result-values">Collecting and handling result values</a> and <a href="/2024/12/02/short-circuiting-an-asynchronous-traversal">Short-circuiting an asynchronous traversal</a>, I realized that it might be valuable to describe a more disciplined variation of the <a href="/2020/03/02/impureim-sandwich">Impureim Sandwich</a> pattern. </p> <p> The book <a href="/ref/dp">Design Patterns</a> describes each pattern over a number of sections. There's a description of the overall motivation, the structure of the pattern, UML diagrams, examples code, and more. One section discusses various implementation variations. I find it worthwhile, too, to explicitly draw attention to a particular variation of the more overall Impureim Sandwich pattern. </p> <p> This variation imposes an additional constraint to the general pattern. While this may, at first glance, seem limiting, <a href="https://www.dotnetrocks.com/details/1542">constraints liberate</a>. </p> <p> <img src="/content/binary/impureim-superset-of-recawr.png" alt="A subset labeled 'Recawr Sandwiches' contained in a superset labeled 'Impureim Sandwiches'."> </p> <p> As a specialization, you may consider Recawr Sandwiches as a subset of all Impureim Sandwiches. </p> <h3 id="7b076cc0cc9148b9ba464bf41feb6128"> Read, calculate, write <a href="#7b076cc0cc9148b9ba464bf41feb6128">#</a> </h3> <p> In short, the constraint is that the Sandwich should be organized in the following order: </p> <ul> <li>Read data. This step is impure.</li> <li>Calculate a result from the data. This step is a <a href="https://en.wikipedia.org/wiki/Pure_function">pure function</a>.</li> <li>Write data. This step is impure.</li> </ul> <p> If the sandwich has <a href="/2023/10/09/whats-a-sandwich">more than three layers</a>, this order should still be maintained. Once you start writing data to the network, to disk, to a database, or to the user interface, you shouldn't go back to reading in more data. </p> <h3 id="12089f0da99644849da33faf7dd8ffa4"> Naming <a href="#12089f0da99644849da33faf7dd8ffa4">#</a> </h3> <p> The name <em>Recawr Sandwich</em> is made from the first letters of <em>REad CAlculate WRite</em>. It's pronounced <em>recover sandwich</em>. </p> <p> When the idea of naming this variation originally came to me, I first thought of the name <em>read/write sandwich</em>, but then I thought that the most important ingredient, the pure function, was missing. I've considered some other variations, such as <em>read, pure, write sandwich</em> or <em>input, referential transparency, output sandwich</em>, but none of them quite gets the point across, I think, in the same way as <em>read, calculate, write</em>. </p> <h3 id="954558da563244edbb98a6685b3f9460"> Precipitating example <a href="#954558da563244edbb98a6685b3f9460">#</a> </h3> <p> To be clear, I've been applying the Recawr Sandwich pattern for years, but it sometimes takes a counter-example before you realize that some implicit, tacit knowledge should be made explicit. This happened to me as I was discussing <a href="/2024/11/18/collecting-and-handling-result-values">this implementation</a> of Impureim Sandwich: </p> <p> <pre><span style="color:green;">//&nbsp;Impure</span> <span style="color:#2b91af;">IEnumerable</span>&lt;<span style="color:#2b91af;">OneOf</span>&lt;<span style="color:#2b91af;">ShoppingListItem</span>,&nbsp;<span style="color:#2b91af;">NotFound</span>&lt;<span style="color:#2b91af;">ShoppingListItem</span>&gt;,&nbsp;<span style="color:#2b91af;">Error</span>&gt;&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">results</span>&nbsp;= &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">itemsToUpdate</span>.<span style="font-weight:bold;color:#74531f;">Traverse</span>(<span style="font-weight:bold;color:#1f377f;">item</span>&nbsp;=&gt;&nbsp;<span style="color:#74531f;">UpdateItem</span>(<span style="font-weight:bold;color:#1f377f;">item</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">dbContext</span>)); <span style="color:green;">//&nbsp;Pure</span> <span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">result</span>&nbsp;=&nbsp;<span style="font-weight:bold;color:#1f377f;">results</span>.<span style="font-weight:bold;color:#74531f;">Aggregate</span>( &nbsp;&nbsp;&nbsp;&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">BulkUpdateResult</span>([],&nbsp;[],&nbsp;[]), &nbsp;&nbsp;&nbsp;&nbsp;(<span style="font-weight:bold;color:#1f377f;">state</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">result</span>)&nbsp;=&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">result</span>.<span style="font-weight:bold;color:#74531f;">Match</span>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">storedItem</span>&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">state</span>.<span style="font-weight:bold;color:#74531f;">Store</span>(<span style="font-weight:bold;color:#1f377f;">storedItem</span>), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">notFound</span>&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">state</span>.<span style="font-weight:bold;color:#74531f;">Fail</span>(<span style="font-weight:bold;color:#1f377f;">notFound</span>.Item), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-weight:bold;color:#1f377f;">error</span>&nbsp;=&gt;&nbsp;<span style="font-weight:bold;color:#1f377f;">state</span>.<span style="font-weight:bold;color:#74531f;">Error</span>(<span style="font-weight:bold;color:#1f377f;">error</span>))); <span style="color:green;">//&nbsp;Impure</span> <span style="color:blue;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">dbContext</span>.<span style="font-weight:bold;color:#74531f;">SaveChangesAsync</span>(); <span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">OkResult</span>(<span style="font-weight:bold;color:#1f377f;">result</span>);</pre> </p> <p> Notice that the top impure step traverses a collection of items to apply each to an action called <code>UpdateItem</code>. As I discussed in the article, I don't actually know what <code>UpdateItem</code> does, but the name strongly suggests that it updates a particular database row. Even if the actual write doesn't happen until <code>SaveChangesAsync</code> is called, this still seems off. </p> <p> To be honest, I didn't realize this until I started thinking about how I'd go about solving the implied problem, if I had to do it from scratch. Because I probably wouldn't do it like that at all. </p> <p> It strikes me that doing the update 'too early' makes the code more complicated than it has to be. </p> <p> What would a Recawr Sandwich look like? </p> <h3 id="e599dadd006a4d179289ba72a1978c1f"> Recawr example <a href="#e599dadd006a4d179289ba72a1978c1f">#</a> </h3> <p> Perhaps one could instead start by querying the database about which items are actually in it, then prepare the result, and finally make the update. </p> <p> <pre><span style="color:green;">//&nbsp;Read</span> <span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">existing</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;<span style="color:#74531f;">FilterExisting</span>(<span style="font-weight:bold;color:#1f377f;">itemsToUpdate</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">dbContext</span>); <span style="color:green;">//&nbsp;Calculate</span> <span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">result</span>&nbsp;=&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">BulkUpdateResult</span>([..&nbsp;<span style="font-weight:bold;color:#1f377f;">existing</span>],&nbsp;[..&nbsp;<span style="font-weight:bold;color:#1f377f;">itemsToUpdate</span>.<span style="font-weight:bold;color:#74531f;">Except</span>(<span style="font-weight:bold;color:#1f377f;">existing</span>)],&nbsp;[]); <span style="color:green;">//&nbsp;Write</span> <span style="color:blue;">var</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">results</span>&nbsp;=&nbsp;<span style="color:blue;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">existing</span>.<span style="font-weight:bold;color:#74531f;">Traverse</span>(<span style="font-weight:bold;color:#1f377f;">item</span>&nbsp;=&gt;&nbsp;<span style="color:#74531f;">UpdateItem</span>(<span style="font-weight:bold;color:#1f377f;">item</span>,&nbsp;<span style="font-weight:bold;color:#1f377f;">dbContext</span>)); <span style="color:blue;">await</span>&nbsp;<span style="font-weight:bold;color:#1f377f;">dbContext</span>.<span style="font-weight:bold;color:#74531f;">SaveChangesAsync</span>(); <span style="font-weight:bold;color:#8f08c4;">return</span>&nbsp;<span style="color:blue;">new</span>&nbsp;<span style="color:#2b91af;">OkResult</span>(<span style="font-weight:bold;color:#1f377f;">result</span>);</pre> </p> <p> To be honest, this variation has different behaviour when <code>Error</code> values occur, but then again, I wasn't entirely sure what was even the purpose of the error value. If it's to <a href="/2024/01/29/error-categories-and-category-errors">model errors that client code can't recover from</a>, throw an exception instead. </p> <p> In any case, the example is typical of many <a href="https://en.wikipedia.org/wiki/Input/output">I/O</a>-heavy operations, which veer dangerously close to the degenerate. There really isn't a lot of logic required, so one may reasonably ask whether the example is useful. It was, however, the example that got me thinking about giving the Recawr Sandwich an explicit name. </p> <h3 id="ef69b33222b44b3e889fc0c861537d48"> Other examples <a href="#ef69b33222b44b3e889fc0c861537d48">#</a> </h3> <p> All the examples in the original <a href="/2020/03/02/impureim-sandwich">Impureim Sandwich</a> article are actually Recawr Sandwiches. Other articles with clear Recawr Sandwich examples are: </p> <ul> <li><a href="/2019/09/09/picture-archivist-in-haskell">Picture archivist in Haskell</a></li> <li><a href="/2019/09/16/picture-archivist-in-f">Picture archivist in F#</a></li> <li><a href="/2021/09/06/the-command-handler-contravariant-functor">The Command Handler contravariant functor</a></li> <li><a href="/2024/12/16/a-restaurant-sandwich">A restaurant sandwich</a></li> </ul> <p> In other words, I'm just retroactively giving these examples a more specific label. </p> <p> What's an example of an Impureim Sandwich which is <em>not</em> a Recawr Sandwich? Ironically, the first example in this article. </p> <h3 id="95dbd8e6364d429db7f040835d89e8e7"> Conclusion <a href="#95dbd8e6364d429db7f040835d89e8e7">#</a> </h3> <p> A Recawr Sandwich is a specialization of the slightly more general Impureim Sandwich pattern. It specializes by assigning roles to the two impure layers of the sandwich. In the first, the code reads data. In the second impure layer, it writes data. In between, it performs referentially transparent calculations. </p> <p> While more constraining, this specialization offers a good rule of thumb. Most well-designed sandwiches follow this template. </p> </div><hr> This blog is totally free, but if you like it, please consider <a href="https://blog.ploeh.dk/support">supporting it</a>. Mark Seemann https://blog.ploeh.dk/2025/01/13/recawr-sandwich