<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andreas Jim</title>
    <description>The latest articles on DEV Community by Andreas Jim (@devkat).</description>
    <link>https://dev.to/devkat</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F371523%2Fc94c3e66-0cbe-43d3-be48-3d214823d586.png</url>
      <title>DEV Community: Andreas Jim</title>
      <link>https://dev.to/devkat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devkat"/>
    <language>en</language>
    <item>
      <title>Scala: A Love Story</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Wed, 21 Apr 2021 13:57:49 +0000</pubDate>
      <link>https://dev.to/devkat/scala-a-love-story-2fe2</link>
      <guid>https://dev.to/devkat/scala-a-love-story-2fe2</guid>
      <description>&lt;h4&gt;
  
  
  I wrote my first programs when I was 14, in Basic on a Sinclair ZX81. Now, looking back at almost 30 years of writing software from 3-line scripts to enterprise content management systems and microservices in the cloud, maybe a handful experiences stand out. Starting to program in Scala is one of them.
&lt;/h4&gt;

&lt;p&gt;Until 2010, I had programmed mostly back-end code, and almost exclusively in Java. I had used quite a few other languages, it was just that none of them seemed to have any clear advantages. Java came with a huge ecosystem of frameworks and libraries, and I felt like the verbosity was an adequate price to pay for type safety.&lt;/p&gt;

&lt;p&gt;At one point I had the opportunity to be the technical lead for a large in-browser application. We started out using plain JavaScript while trying to adhere to the functional paradigm: Avoid mutability, favour evaluation over execution. In the beginning this worked reasonably well. The codebase was small, the code was concise and easy to read, we were able to deliver features at a remarkable pace. But when the codebase grew and more developers joined the team, our productivity started to decline. We had to add (and maintain) more code documentation. It was nearly impossible to change something in a core module, there were just too many potential usages, particularly in a dynamically typed language that supports implicit type conversion and allows things like &lt;code&gt;something[methodName]();&lt;/code&gt;. In the end we ended up migrating the critical modules to TypeScript, which improved the situation considerably. Lesson learned.&lt;/p&gt;

&lt;p&gt;But the experience from the early days of our JavaScript project stuck with me. It felt like with Java, and with the frameworks we used, there was no linear relation between the complexity of the models or logic you wanted to implement, and the amount of code you had to write. Even the simplest tasks required a lot of boilerplate. The nagging question kept popping up in the back of my mind: Why can't we everything at once: Concise code, type safety, record types, closures? There had to be something better.&lt;/p&gt;

&lt;p&gt;I purchased the very entertaining book &lt;a href="https://www.oreilly.com/library/view/seven-languages-in/9781680500059/"&gt;Seven Languages in Seven Weeks&lt;/a&gt;. Although I found Haskell fascinating and tempting, I knew it was unrealistic to introduce it in our company. Scala on the other hand looked like it could be the holy grail: All the characteristics I was looking for, no need to abandon the JVM and its cornucopia of tools and libraries, and the possibility for coexistence with Java and therefore incremental adoption. After implementing some simple programs to identify any immediate risks of committing to the language and its ecosystem, I started to introduce Scala in customer projects. Luckily, I was fortunate enough to work with open-minded, curious, and ambitious team members who were also experienced enough to appreciate the benefits of the language. We immediately applied our experience with functional programming, and embraced immutability. Libraries like &lt;a href="http://scala-slick.org"&gt;Slick&lt;/a&gt; and &lt;a href="https://doc.akka.io/docs/akka-http/current/index.html"&gt;Akka HTTP&lt;/a&gt; (we actually started out with its predecessor, &lt;a href="http://spray.io"&gt;Spray&lt;/a&gt;) made building database-backed REST services a breeze. And the resulting code was robust and highly maintainable. Scala's expressive type system and type inference made it easy to build a restrictive, consistent domain model without bloating the code. There was virtually no overhead. Any boilerplate could be easily abstracted out. In the end, the application code felt natural, concise and elegant. Programming was fun again.&lt;/p&gt;

&lt;p&gt;The name Scala is portmanteau of &lt;em&gt;scalable&lt;/em&gt; and &lt;em&gt;language&lt;/em&gt;. This is far from a marketing ploy. The language is designed from the ground up to excel in the full spectrum from 3-line scripts to vast, high-performance distributed systems. From my experience, I would attribute this to the following characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scala's syntax is particularly suited for building APIs and DSLs.&lt;/li&gt;
&lt;li&gt;Its expressive type system (higher-kinded types etc.) encourages abstraction and generic programming.&lt;/li&gt;
&lt;li&gt;Scala supports functional programming, and functional programs are inherently composable.&lt;/li&gt;
&lt;li&gt;There is are many excellent libraries that leverage these features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scala has sparked a huge ecosystem of very high quality libraries (&lt;a href="https://typelevel.org/cats/"&gt;Cats&lt;/a&gt;, &lt;a href="https://scalaz.github.io/7/"&gt;Scalaz&lt;/a&gt;, &lt;a href="https://github.com/milessabin/shapeless"&gt;shapeless&lt;/a&gt;, to name but a few). I think a major reason for this is that Scala attracts developers who value the advantages of the JVM, but are fed up with the limitations of the Java programming language and understand the benefits of an expressive type system and functional programming.&lt;/p&gt;

&lt;p&gt;Admittedly, it is not trivial to transition from imperative to functional programming. At first glance, some of the functional concepts seem alien and overly complicated, and many beginner tutorials already confront the reader with terms from category theory. If somebody with an imperative background commits themselves to the functional paradigm, they usually have a thorough understanding of its benefits, and why (and when) the transition is worthwhile.&lt;/p&gt;

&lt;p&gt;After having programmed almost exclusively in Java for eight months, I miss the convenience of the Scala language and its standard library. In Scala, everything fits together seamlessly, types can be composed and decomposed, there is no need to write boilerplate-ridden classes for simple data types or shoehorn data into unsafe, cumbersome collection types. Scala, I miss you, and I hope we will meet again one day.&lt;/p&gt;

</description>
      <category>scala</category>
      <category>programming</category>
    </item>
    <item>
      <title>Quiz: Is Scala for me?</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Fri, 19 Mar 2021 13:42:25 +0000</pubDate>
      <link>https://dev.to/devkat/quiz-is-scala-for-me-4cm4</link>
      <guid>https://dev.to/devkat/quiz-is-scala-for-me-4cm4</guid>
      <description>&lt;p&gt;You're currently programming in Java (or any other language for that matter), and wonder whether learning Scala might be worth the effort? Here's a little quiz to help you decide.&lt;/p&gt;

&lt;p&gt;Disclaimer: This is just a rough guide based on my experience, and should be taken with two grains of salt 😉&lt;/p&gt;

&lt;h4&gt;
  
  
  You have a function that calculates the sum of a list of numbers. You have to provide the same functionality for lists of strings (concatenate) and lists of lists (append).
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I duplicate the function for each data type. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I think about how to make the function generic so that it operates on these three data types, then I refactor it accordingly. &lt;em&gt;(1 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I implement a monoid type (or include a library which provides one) and change the function to operate on lists of monoids. &lt;em&gt;(2 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  When writing software, do you think in short or long terms?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I want to get things done now. Maybe I will never touch this code again, and my program will be irrelevant next year. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;My code will outlast me. New requirements after five years? I'm not worried, I deliberately design my code to be maintainable. &lt;em&gt;(2 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  What do you do when you something bothers you in a programming language?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I live with it, it's just one of those things. Nothing is ever perfect. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I implement a workaround and publish it as an open-source library. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How would you describe yourself?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I do what I'm good at, and I do it the way I'm used to. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'm curious, ambitious and always up for a challenge. &lt;em&gt;(2 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  What type of technology do you prefer?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I want to be productive immediately, without learning new concepts. I don't know when I have to switch to something else again. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'm willing to invest some time to learn unfamiliar concepts, if I see the long-term benefits. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  What is your opinion on &lt;code&gt;null&lt;/code&gt; references?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;They are useful and convenient. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They are sometimes bothersome, but I didn't really think about it yet. &lt;code&gt;NullPointerException&lt;/code&gt;s are just part of life. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;null&lt;/code&gt; is terrible. I'm aware of &lt;code&gt;java.util.Optional&lt;/code&gt;, but this is such a controversial subject that I haven't yet committed to it. &lt;em&gt;(1 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;null&lt;/code&gt; belongs in hell, and option types are a useful replacement. I just wish &lt;code&gt;java.util.Optional&lt;/code&gt; wouldn't be so limited, and that it would be used everywhere. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How do you feel about static vs dynamic typing?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The type system is always in the way. I find it too restrictive. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I like static typing, it helps with autocomplete and catches mistakes during compile time. &lt;em&gt;(1 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An expressive static type system allows me to build safe and consistent domain models, and to write better code in general. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  What is your opinion on runtime errors?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When they occur, I fix them. Nobody can anticipate everything. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That's what unit tests are for. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I design my code to be robust, and handle any potential exceptions. &lt;em&gt;(1 point)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code safety is one of my major design concerns. By accurately modelling my data and treating errors as first-class citizens I can avoid runtime errors almost entirely. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How do you prevent regressions?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Q/A department is responsible for regression testing. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have unit tests with 120% code coverage. &lt;em&gt;(0 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have carefully designed the domain model using advanced type system features based on category theory, and I implemented a guarded finite state machine DSL that allows me to generate the workflow code directly from the specification. &lt;em&gt;(2 points)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;0 points: Don't touch Scala with a long stick.&lt;/p&gt;

&lt;p&gt;18 points: Head straight to the &lt;a href="https://www.scala-lang.org"&gt;download page&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Anything in between: Maybe it's worth taking a closer look?&lt;/p&gt;

</description>
      <category>scala</category>
    </item>
    <item>
      <title>Safe Domain Objects with MapStruct and Immutables</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Wed, 16 Dec 2020 09:45:24 +0000</pubDate>
      <link>https://dev.to/devkat/safe-domain-objects-with-mapstruct-and-immutables-24hn</link>
      <guid>https://dev.to/devkat/safe-domain-objects-with-mapstruct-and-immutables-24hn</guid>
      <description>&lt;h4&gt;
  
  
  Even in Java you are not doomed to deal with mutable objects and nullable fields. With the help of annotation processor libraries like MapStruct and Immutables you can add some safety and convenience to your codebase.
&lt;/h4&gt;

&lt;p&gt;During the last couple of months I have been working with Java, using mutable POJOs as domain objects and &lt;a href="https://mybatis.org/mybatis-3/"&gt;MyBatis&lt;/a&gt; for database access. Queries are declared in XML files, with only some &lt;a href="https://mybatis.org/mybatis-3/dynamic-sql.html"&gt;basic and rather cumbersome support&lt;/a&gt; for modularisation and code reuse. Why would I want to deal with another XML-based expression language, when I have a perfectly capable programming language with complete IDE support at my disposal?&lt;/p&gt;

&lt;p&gt;Without the compiler protecting me from my own mistakes and the dreaded &lt;code&gt;NullPointerException&lt;/code&gt; lurking behind every corner, I dearly missed the comfort and safety of the Scala ecosystem. So I started wondering how to get something akin to &lt;a href="https://docs.scala-lang.org/tour/case-classes.html"&gt;case classes&lt;/a&gt; and &lt;a href="https://getquill.io"&gt;Quill&lt;/a&gt; in the cold and harsh winter of the Java world. Let's start with a brief wishlist.&lt;/p&gt;

&lt;p&gt;All I want for Christmas is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A substitute for case classes — immutable objects, preferrably with support for cloning (with modified fields) and &lt;a href="https://lahteenmaki.net/dev_*16/#/"&gt;optics&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Support for mapping primitive database fields to enums, value classes and complex types.&lt;/li&gt;
&lt;li&gt;Dedicated domain objects for creating and reading (more on this below).&lt;/li&gt;
&lt;li&gt;Type-safe, modular queries.&lt;/li&gt;
&lt;li&gt;Minimal boilerplate would be the icing on the gingerbread biscuit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Libraries
&lt;/h1&gt;

&lt;p&gt;After a little bit of research, I identified the following libraries as possible candidates for the persistence and domain layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://immutables.github.io"&gt;Immutables&lt;/a&gt; — Annotation processor to generate simple, safe and consistent value objects&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mapstruct.org"&gt;MapStruct&lt;/a&gt; — Another annotation processor; we will use it to map between domain objects and &lt;a href="https://en.wikipedia.org/wiki/Data_transfer_object"&gt;data transfer objects (DTOs)&lt;/a&gt;. I picked this library out of several similar ones since it seems to be mature and performant and supports Immutables out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.jinq.org"&gt;Jinq&lt;/a&gt; — Type-safe queries&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.functionaljava.org"&gt;Functional Java&lt;/a&gt; — Because we can't have &lt;a href="https://typelevel.org/cats/"&gt;Cats&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example code for this article can be found on &lt;a href="https://github.com/devkat/mapstruct-immutable-example"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Domain Model
&lt;/h1&gt;

&lt;p&gt;Let's start with our domain model. We define the interfaces of our domain objects and let Immutables generate the implementations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt; &lt;span class="nd"&gt;@Tuple&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt; &lt;span class="nd"&gt;@Tuple&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Species&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getSpecies&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things worth mentioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;@Tuple&lt;/code&gt; annotation denotes that we would like to use a &lt;a href="https://immutables.github.io/immutable.html#tuple-style"&gt;single static method&lt;/a&gt; to initialize our objects, as opposed to a &lt;a href="https://immutables.github.io/immutable.html#builder"&gt;builder&lt;/a&gt;. This way we can ensure at compile-time that all fields are initialized.&lt;/li&gt;
&lt;li&gt;The type &lt;code&gt;Species&lt;/code&gt; is an enum. JPA can map this to an ordinal value.&lt;/li&gt;
&lt;li&gt;We are using the &lt;code&gt;Option&lt;/code&gt; class from the Functional Java library, a safer and more convenient alternative to Java's &lt;code&gt;Optional&lt;/code&gt;. We use a &lt;a href="https://github.com/devkat/mapstruct-immutable-example/blob/main/src/main/java/com/github/devkat/persistence/conversion/OptionConverter.java"&gt;custom JPA attribute converter&lt;/a&gt; to map this field to a nullable field in the DTO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Domain object identifiers
&lt;/h1&gt;

&lt;p&gt;You may have noticed that our domain classes are lacking an identifier which will mapped to a primary key in the DTO. This is by design: Primary keys are often automatically generated by the database. When we create a new domain object, it doesn't have an identifier yet. We could model it as an &lt;code&gt;Option&lt;/code&gt;, but this wouldn't accurately reflect reality — a domain object &lt;em&gt;never&lt;/em&gt; has an ID before it is persisted, and it &lt;em&gt;always&lt;/em&gt; has an ID when it has been retrieved from the database. Instead, we wrap our domain object in a separate object to augment it with the ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="no"&gt;ID&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="no"&gt;A&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will use value objects for our IDs as an additional safety measure. Luckily, Immutables supports them out of the box by means of &lt;a href="https://immutables.github.io/immutable.html#wrapper-types"&gt;wrapper types&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt; &lt;span class="nd"&gt;@Wrapped&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_BookId&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt; &lt;span class="nd"&gt;@Wrapped&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_CharacterId&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Wrapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on these definitions, the Immutables annotation processor will generate the concrete classes &lt;code&gt;BookId&lt;/code&gt; and &lt;code&gt;CharacterId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Last but not least, we define a many-to-many relation between books and characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Immutable&lt;/span&gt; &lt;span class="nd"&gt;@Tuple&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookToCharacter&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;BookId&lt;/span&gt; &lt;span class="nf"&gt;getBookId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;CharacterId&lt;/span&gt; &lt;span class="nf"&gt;getCharacterId&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Data transfer objects (DTOs)
&lt;/h1&gt;

&lt;p&gt;Due to the limitations of JPA, in addition to our domain classes, we have to use dedicated mutable classes for the data transfer objects. This results in quite a bit of knowledge duplication and boilerplate. If you know a solution for this problem, I would be very happy to hear about it in the comments section. It would more or less render this article obsolete, which I wouldn't be particularly unhappy about.&lt;/p&gt;

&lt;p&gt;Since the DTOs are significantly more verbose than the domain objects, I will only show the most relevant sections.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookDto&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;WithIdDto&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toEntity&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Getters and setters&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CharacterDto&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;WithIdDto&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toEntity&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Enumerated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EnumType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ORDINAL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Convert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;converter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OptionConverter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Species&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;species&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Getters and setters&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both of these classes implement the &lt;code&gt;WithIdDto&lt;/code&gt; interface, which defines the &lt;code&gt;toEntity()&lt;/code&gt; method. This method allows us to convert a DTO to the domain object, including the ID which is derived from the primary key.&lt;/p&gt;

&lt;p&gt;And, last but not least, the DTO for our relation, which uses a composite primary key. We are using an &lt;code&gt;@IdClass&lt;/code&gt; instead of an &lt;code&gt;@EmbeddedId&lt;/code&gt; to simplify the mapping from/to the domain class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@IdClass&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BookToCharacterDto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BookToCharacterId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookToCharacterDto&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookToCharacterId&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bookId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;characterId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Constructor and getters&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bookId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;characterId&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Getters and setters&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Mapping between domain objects and DTOs
&lt;/h1&gt;

&lt;p&gt;The heavy lifting is done by MapStruct, we just have to declare our mappers. First, we define a common interface for all domain-object-to-DTO mappers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DtoMapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;E&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;D&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="no"&gt;D&lt;/span&gt; &lt;span class="nf"&gt;toDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="no"&gt;E&lt;/span&gt; &lt;span class="nf"&gt;fromDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="no"&gt;D&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we declare the individual mappers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;static&lt;/span&gt; &lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mapstruct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Mappers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMapper&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mappers&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Mapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BookIdMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookMapper&lt;/span&gt;
            &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;DtoMapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BookDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;BookMapper&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BookMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Mapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CharacterIdMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;CharacterMapper&lt;/span&gt;
            &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;DtoMapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CharacterMapper&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CharacterMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Mapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nc"&gt;BookIdMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;CharacterIdMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;BookToCharacterMapper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;BookToCharacterMapper&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;getMapper&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BookToCharacterMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;BookToCharacterDto&lt;/span&gt; &lt;span class="nf"&gt;toDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BookToCharacter&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;BookToCharacterMapper&lt;/code&gt; doesn't extend &lt;code&gt;DtoMapper&lt;/code&gt;; for some reason MapStruct refused to generate the mapper class.&lt;/p&gt;

&lt;p&gt;I implemented a custom mapper for each wrapper type. There is probably a way to get rid of this boilerplate, but it didn't bother me enough yet to spend more time on this issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookIdMapper&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;BookId&lt;/span&gt; &lt;span class="nf"&gt;asBookId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;asInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;BookId&lt;/span&gt; &lt;span class="n"&gt;bookId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bookId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, let's take a quick look at the implementation of the &lt;code&gt;toEntity&lt;/code&gt; method in our DTOs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookDto&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;WithIdDto&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;toEntity&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ImmutableWithId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                &lt;span class="nc"&gt;Mappers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;BookMapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// …&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Querying data
&lt;/h1&gt;

&lt;p&gt;Now that we have declared our domain objects and defined how they are persisted, we can start using them. I won't go into the details of building queries with Jinq — this is covered extensively in the documentation — and rather just show some example code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BookService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractPersistenceService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="err"&gt;…&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;P2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
                &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getBooksWithCharacters&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;iterableStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;leftOuterJoin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BookToCharacterDto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBookId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;leftOuterJoin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CharacterDto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
                        &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTwo&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getCharacterId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;TupleOps:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;TupleOps:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;p2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;P2:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;_1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;WithIdDto:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;toEntity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;WithIdDto:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;toEntity&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this level, we still have to deal with the DTO classes, but only to build queries, so there is no danger of introducing mutable state.&lt;/p&gt;

&lt;p&gt;The joins result in nested Jinq tuples. At the end we transform these tuples into FunctionalJava tuples, and map the contained DTOs to their respective entities. In a real-world project, I would make this code generic and reuse it across all services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using the service
&lt;/h1&gt;

&lt;p&gt;Now we can take a look at our test method, which persists and reads domain objects using the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;testPersistence&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;transactional&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="n"&gt;bookService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ImmutableBook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Night Watch"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Effect1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;addCharacter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="n"&gt;bookService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createCharacter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;bookService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addCharacterToBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;chRead&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
            &lt;span class="o"&gt;};&lt;/span&gt;

            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt; &lt;span class="n"&gt;vimes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImmutableCharacter&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Samuel Vimes"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;HUMAN&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt; &lt;span class="n"&gt;nobby&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImmutableCharacter&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;copyOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vimes&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nobby Nobbs"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withSpecies&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

            &lt;span class="n"&gt;addCharacter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vimes&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;addCharacter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;f&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nobby&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

            &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;P2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
                &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BookId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;WithId&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CharacterId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;booksWithCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                    &lt;span class="n"&gt;bookService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBooksWithCharacters&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;assertTrue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;booksWithCharacters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

            &lt;span class="n"&gt;booksWithCharacters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foreach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;bk&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s (%s)%n"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getData&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                    &lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getData&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getSpecies&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="o"&gt;}));&lt;/span&gt;

        &lt;span class="o"&gt;});&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;We have managed to address some critical pain points, in particular we can map between immutable domain objects and DTOs with a reasonable amout of boilerplate and uild type-safe queries using Java code.&lt;/p&gt;

&lt;p&gt;Evidently, there is quite a bit of room for improvement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our implementation supports both the Builder style (for MapStruct) and the Tuple style (for our code). Using the Builder style can lead to runtime errors since it doesn't ensure at compile time that all fields are initialised. Please leave a comment if you know how to get MapStruct to use the Tuple style for mapping.&lt;/li&gt;
&lt;li&gt;The error messages emitted by the MapStruct and Immutables annotation processors leave a lot to be desired. I'm not particularly fond of meta programming in general; this experience confirms my preconception. Maybe it is possible to get more information by setting compiler arguments, but my attempts were unsuccessful.&lt;/li&gt;
&lt;li&gt;Jinq queries are not completely type-safe, there can still be runtime errors ("Could not analyze lambda code").&lt;/li&gt;
&lt;li&gt;We are not treating effects as &lt;a href="https://dev.to/devkat/effects-and-the-illusion-of-correctness-258j"&gt;first-class citizens&lt;/a&gt;. The Functional Java library provides an &lt;code&gt;IO&lt;/code&gt; type for this purpose, but this is a topic for a future article.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>persistence</category>
      <category>modelling</category>
    </item>
    <item>
      <title>Interpreting Tagless Final DSLs with Eff</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Wed, 13 May 2020 12:03:21 +0000</pubDate>
      <link>https://dev.to/devkat/interpreting-tagless-final-dsls-with-eff-591d</link>
      <guid>https://dev.to/devkat/interpreting-tagless-final-dsls-with-eff-591d</guid>
      <description>&lt;p&gt;Liquid syntax error: 'raw' tag was never closed&lt;/p&gt;
</description>
      <category>functional</category>
      <category>scala</category>
      <category>taglessfinal</category>
    </item>
    <item>
      <title>Cooking with Monads</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Wed, 13 May 2020 11:42:34 +0000</pubDate>
      <link>https://dev.to/devkat/cooking-with-monads-30k5</link>
      <guid>https://dev.to/devkat/cooking-with-monads-30k5</guid>
      <description>&lt;p&gt;Liquid syntax error: 'raw' tag was never closed&lt;/p&gt;
</description>
      <category>functional</category>
      <category>scala</category>
    </item>
    <item>
      <title>Effects and the Illusion of Correctness</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Fri, 01 May 2020 09:56:12 +0000</pubDate>
      <link>https://dev.to/devkat/effects-and-the-illusion-of-correctness-258j</link>
      <guid>https://dev.to/devkat/effects-and-the-illusion-of-correctness-258j</guid>
      <description>&lt;p&gt;&lt;strong&gt;Imperative programming makes it easy to write complex programs, but hard to write correct ones. One reason for this is that imperative languages refuse to properly deal with effects. The article shows why effects should treated as first-class citizens and how things can be improved by switching from imperative to functional programming.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every useful computer program interacts with the world outside the actual source code, typically by reading and writing data from storage media and over network connections. Programmers call such an interaction an &lt;em&gt;effect&lt;/em&gt;. Every time a program performs an effect, it leaves the safe, predictable environment of the program flow — a file can be missing, a server can be down. The inherent dangers of effects are undeniable, therefore how a program deals with effects makes all the difference.&lt;/p&gt;

&lt;h1&gt;
  
  
  Effects in Imperative Programming
&lt;/h1&gt;

&lt;p&gt;Many software developers begin their journey with imperative programming. Usually it is immediately obvious what an imperative program is intended to do. Therefore such programs look simple, straightforward, and not intimidating.&lt;/p&gt;

&lt;p&gt;The basis of each imperative program is a mental model of the execution flow of the program, typically derived from the “main success scenario” of a use case in the requirements specification. Since our cognitive capacity is limited, this model is — and has to be — a simplified one; nobody is capable of considering all possible execution flows of a reasonably complex real-world program at the same time.&lt;/p&gt;

&lt;p&gt;Now, this mental model has to be expressed in the form of &lt;em&gt;statements&lt;/em&gt;. As an inexperienced programmer, you approach this like an impatient and ignorant manager: You tell your employees (or in this case, the machine) what to do and you can’t be bothered with all the little risks and pitfalls that executing the tasks might actually entail. The fatal problem is that the programming language gives you the illusion that you have created a correct program, and you let yourself succumb to this illusion due to your lack of experience or dedication.&lt;/p&gt;

&lt;p&gt;Consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.io.Source&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;readFileImp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fromFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;lines&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getLines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;
  &lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;close&lt;/span&gt;
  &lt;span class="n"&gt;lines&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;readFileImp&lt;/code&gt; method is clearly intended to read a list of lines file. But the fact that I'm using the verb &lt;em&gt;intended&lt;/em&gt; indicates that this is not what the program actually does, at least not in all situations. What will happen if the file doesn't exist? In this case the program doesn't do what you intend it to do.&lt;/p&gt;

&lt;p&gt;The problem here is that imperative languages usually don’t explicitly address the subject of effects. They don’t distinguish between safe and unsafe operations. The execution of each line could potentially result in an error. The programming language couldn’t care less — it doesn’t support you in the difficult task of writing correct software. Instead, it shifts the cognitive burden to you, the programmer. When writing or reviewing code, you have to continuously &lt;em&gt;think&lt;/em&gt; about whether it could contain any hidden problems. This makes it incredibly hard to produce correct code — for a seasoned developer it is very stressful, for a beginner it is virtually impossible.&lt;/p&gt;

&lt;p&gt;Most imperative programming languages provide the developer with a crutch to handle those hidden problems: Exceptions. The mere term spotlights the fact that imperative languages promote the practice of reflecting only a certain intended scenario in the source code. The developer is not supposed to clutter the code with the handling of undesirable cases. If a so-called exception occurs, it just stops the execution flow, potentially leaving the program in a hazardous state, and &lt;em&gt;implicitly&lt;/em&gt; bubbles up the call stack, until a benevolent piece of code shows the kindness of handling it or presenting it to the user. If no such piece of code exists, the application gives up and quits. It is up to you, the programmer, to check the documentation of each and every called method for whether it might throw an exception. A programmer may think of exception handling as a safety net, but in reality it just moves the inherent risks of effects from plain view, where it belongs, to a hidden, convoluted side track outside the actual program flow.&lt;/p&gt;

&lt;p&gt;The illusion of correctness that characterises imperative programs comes at a steep price. You can choose which price to pay: Either you live with the illusion at the expense of correctness (which typically involves continuous and extensive bugfixing down the road), or you try to maximise the correctness of your program by carefully examining each line of it and writing a ton of unit tests.&lt;/p&gt;

&lt;h1&gt;
  
  
  Effects in Functional Programming
&lt;/h1&gt;

&lt;p&gt;The functional programming world has a term for code which contains hidden traps: &lt;em&gt;impure&lt;/em&gt;. In contrast, a pure piece of code is innocent — it reveals everything it does in its signature, without hiding any dirty details. Every time you call it with certain parameters you can expect the same result and don’t have to worry about any unforeseeable effects. This property of functional programs is called &lt;a href="https://en.wikipedia.org/wiki/Referential_transparency"&gt;referential transparency&lt;/a&gt;. Any combination of pure functions is again pure, but a single impure piece of code will compromise the purity of the whole program. In languages like Scala which support both the imperative and the functional paradigm, it is crucial to take care not to incorporate any impure code into a program. At times, this can be challenging; especially after years of programming imperatively. But in the end it is well worth it.&lt;/p&gt;

&lt;p&gt;For comparison, here’s a typical functional program offering the same functionality as our example above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cats.effect.IO&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.io.Source&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;readFileFunc&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Throwable&lt;/span&gt;, &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fromFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getLines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;source&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;close&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;attempt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, this program is also not free of errors, e.g. the source will not be closed if an error occurs while the file content is read, but it should be sufficient to illustrate some basic concepts.&lt;/p&gt;

&lt;p&gt;Let’s see how this &lt;code&gt;readFileFunc&lt;/code&gt; function differs from the &lt;code&gt;readFileImp&lt;/code&gt; "function" in the first example. &lt;code&gt;readFileImp&lt;/code&gt; is actually not a function: It claims to return a list of strings, but in reality it is only able to do so if the file actually exists. In contrast to that, the &lt;code&gt;readFileFunc&lt;/code&gt; is honest about its return type. It returns an &lt;code&gt;IO&lt;/code&gt;, which means that the function doesn't actually do anything, it only produces a "process" object which can be executed (e.g. using the &lt;code&gt;unsafeRunSync&lt;/code&gt; method, whose name implies that you're now leaving the safe territory of referential transparency). The &lt;code&gt;readFileFunc&lt;/code&gt; always produces the same process object, in any circumstance. Furthermore, the result type of the &lt;code&gt;IO&lt;/code&gt; is either a &lt;code&gt;Throwable&lt;/code&gt; (i.e. an error object) or a list of strings, which conveys that the execution might actually fail.&lt;/p&gt;

&lt;p&gt;As a functional programmer, you safely compose your program by combining pure functions. Some of these functions might return unsafe processes (like the &lt;code&gt;IO&lt;/code&gt; objects in our example program), but this is explicitly stated in their return type, which means that the caller is always aware of it. Only at the very last moment, after the composed program has been invoked and an effectful process is produced – commonly phrased "the end of the world" – this process and its effects are executed under strict observation.&lt;/p&gt;

&lt;p&gt;The following picture illustrates how imperative and functional programming languages handle effects differently. The explosion symbolizes the execution of an effect; the bomb symbolizes an effect object which is waiting to be executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WeymH-7K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AfLpq0u7WhRkiP6LMdof8bQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WeymH-7K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/1400/1%2AfLpq0u7WhRkiP6LMdof8bQ.png" alt="Imperative vs. functional programming" width="880" height="543"&gt;&lt;/a&gt;&lt;/p&gt;
Icons by &lt;a href="http://www.freepik.com/"&gt;Freepik&lt;/a&gt; and &lt;a href="https://www.flaticon.com/authors/vectors-market"&gt;Vectors Market&lt;/a&gt; from &lt;a href="http://www.flaticon.com/"&gt;www.flaticon.com&lt;/a&gt;



&lt;p&gt;The implicit handling of effects turns the whole imperative program into a minefield, whereas in a functional program effects are explicitly created, composed and executed “at the end of the world”, in a constricted and controlled environment.&lt;/p&gt;

&lt;h1&gt;
  
  
  Scala Libraries
&lt;/h1&gt;

&lt;p&gt;To help you get started with managing effects, here’s a short list of Scala libraries dedicated to this purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/atnos-org/eff"&gt;eff&lt;/a&gt; — Extensible effects based on the “free-er” monad&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/typelevel/cats-effect"&gt;cats-effect&lt;/a&gt; — I/O effects for the cats ecosystem&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/b-studios/scala-effekt"&gt;Scala Effect&lt;/a&gt; — Structuring effectful programs in a functional way&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;While imperative programming hides complexity at the expense of correctness, functional programming aims at ensuring correctness while embracing complexity. If complexity cannot be hidden, it has to be managed. This might be one of the reasons why functional programming is considered to be so hard to learn: A beginner in imperative programming will implement a complex process using a seemingly simple program on the first day, because most of the complexity is implicit and hidden. A beginner in functional programming will only be able to express complex processes after several weeks or months of learning, because he has to gradually build up his knowledge about how to represent all the different aspects of the complex processes in his program. But from the very beginning of this journey, correctness and robustness will be essential and non-negotiable characteristics of his programs.&lt;/p&gt;

&lt;p&gt;I would be very happy to hear about your opinion in the comments section. Thanks a lot for reading!&lt;/p&gt;




&lt;p&gt;Cover image: &lt;a href="https://unsplash.com/photos/E6c9QHSJXq4"&gt;Danger: Hard Hat Area&lt;/a&gt; by &lt;a href="https://unsplash.com/@kjarrett"&gt;Kevin Jarrett&lt;/a&gt; on Unsplash&lt;/p&gt;

</description>
      <category>functional</category>
      <category>architecture</category>
      <category>scala</category>
    </item>
    <item>
      <title>Tagless Final in Scala: Best Practices</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Tue, 21 Apr 2020 08:44:11 +0000</pubDate>
      <link>https://dev.to/devkat/tagless-final-in-scala-best-practices-3a01</link>
      <guid>https://dev.to/devkat/tagless-final-in-scala-best-practices-3a01</guid>
      <description>&lt;h4&gt;
  
  
  Notwithstanding &lt;a href="https://www.slideshare.net/jdegoes/the-death-of-final-tagless"&gt;some&lt;/a&gt; &lt;a href="http://degoes.net/articles/tagless-horror"&gt;criticism&lt;/a&gt;, the tagless final pattern continues to gain popularity among the Scala community. I want to share some things I learned while working with tagless final for about two years.
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://www.becompany.ch/en/blog/2018/06/21/tagless-final"&gt;tagless final&lt;/a&gt; pattern enables the programmer to declare modules with a very specific set of functions, and compose programs based on these modules. The foremost concerns of this approach are correctness and predictability. Today’s article is a collection of best practices and lessons learned and will hopefully help you utilize the pattern to its full potential and avoid any common pitfalls. The concepts and principles presented here are nothing new and will be familiar to every seasoned programmer; the article merely provides some guidance how to apply them in the context of tagless final programs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coding Style Recommendations
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Naming
&lt;/h2&gt;

&lt;p&gt;Let’s start with the most controversial of them all — &lt;a href="https://www.slideshare.net/pirhilton/how-to-name-things-the-hardest-problem-in-programming"&gt;naming&lt;/a&gt;. Although not directly related to tagless final, I find it worth sharing that the following naming scheme has proved to be practical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;becompany&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;AuthnDomain&lt;/span&gt;
&lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;becompany&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;AuthnDsl&lt;/span&gt;
&lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;becompany&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;AuthnService&lt;/span&gt;
&lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;becompany&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;DbDomain&lt;/span&gt;
&lt;span class="nv"&gt;ch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;becompany&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;DbDsl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package and class names are redundant (as opposed to, e.g., &lt;code&gt;ch.becompany.authn.Dsl&lt;/code&gt;), but this scheme has some advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autocomplete is a bit quicker since you don’t have to cycle between alternatives.&lt;/li&gt;
&lt;li&gt;Generally, since each DSL has a unique name, no imports have to be renamed to avoid name collisions. This ensures that the same class name is used everywhere in the codebase, which aids readability.&lt;/li&gt;
&lt;li&gt;Even when you need only one DSL in the scope, you can immediately see which DSL it is.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Context Bound Style and the apply Function
&lt;/h2&gt;

&lt;p&gt;Scala offers two syntactic styles for declaring implicit dependencies: implicit parameters and context bounds. I generally prefer the context bound style because it makes the constraints for a type parameter immediately obvious, and it doesn’t require naming parameters. Here’s an example of the context bound style with multiple type parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;,
&lt;span class="kt"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;LogDsl&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only disadvantage of the context bound style that I’m aware of is that sometimes the compiler has trouble inferring the type parameter when the function is used, and requires a type ascription.&lt;/p&gt;

&lt;p&gt;The companion object of the DSL trait should provide an apply function which can be used to resolve the DSL instance in the current implicit scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;AuthnDsl&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]](&lt;/span&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ev&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This style has the additional benefit that the type of the DSL, in this case &lt;code&gt;F&lt;/code&gt;, is immediately apparent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nc"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="py"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Design Considerations
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Constraints and Overconstraining
&lt;/h2&gt;

&lt;p&gt;A core concept of tagless final is declaring dependencies. The following function declares a dependency to an &lt;code&gt;AuthnDsl&lt;/code&gt; instance for the type &lt;code&gt;F&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
  &lt;span class="nc"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="py"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each dependency can also be viewed as a &lt;em&gt;constraint&lt;/em&gt; on the type &lt;code&gt;F&lt;/code&gt;, since it reduces the set of all possible concrete type instances for &lt;code&gt;F&lt;/code&gt;. Each function should only declare those constraints that its implementation actually needs, for the following reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fewer constraints a function has, the more types it supports. In other words, functions with fewer type constraints are more generic and can be applied in more situations.&lt;/li&gt;
&lt;li&gt;Each additional constraint increases the capabilities of a function. The more capabilities a function has, the less predictable it becomes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The relationship between constraints and reasoning is one of the key benefits of programming with effects and the tagless final approach: Given that its implementation is disciplined, i.e. it doesn’t directly invoke any side effects, it is possible to predict what operations the resulting effect instance can contain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CaNPqDAB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/620/0%2AwNGIYDXMOXer8LLY.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CaNPqDAB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/620/0%2AwNGIYDXMOXer8LLY.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EmailDsl&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just by looking at the function signature, without knowing anything about its implementation, you can be sure that the effect instance returned by this function can only&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute effects related to authentication,&lt;/li&gt;
&lt;li&gt;Execute effects related to e-mail, and&lt;/li&gt;
&lt;li&gt;Combine the results using &lt;a href="https://www.becompany.ch/en/blog/2016/11/08/cooking-with-monads"&gt;monadic operations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let’s see what happens when we replace the &lt;code&gt;Monad&lt;/code&gt; constraint with the &lt;a href="https://typelevel.org/cats-effect/typeclasses/sync.html"&gt;&lt;code&gt;Syn&lt;/code&gt;c&lt;/a&gt; constraint from the &lt;a href="https://typelevel.org/cats-effect"&gt;cats-effect&lt;/a&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerUser&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EmailDsl&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Sync&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This change opens Pandora’s box. The function can now suspend arbitrary side effects in the returned effect instance — it could, to quote a coworker, “launch a rocket”. In addition, it can potentially instantiate other DSL interpreters which declare the &lt;code&gt;Sync&lt;/code&gt; constraint. It is impossible to know what executing the effect instance returned by this registerUser function will actually do.&lt;/p&gt;

&lt;p&gt;The practice of declaring unnecessary constraints, also called &lt;em&gt;overconstraining&lt;/em&gt;, violates the &lt;a href="http://www.lihaoyi.com/post/StrategicScalaStylePrincipleofLeastPower.html"&gt;principle of least power&lt;/a&gt; and should generally be considered a &lt;a href="https://en.wikipedia.org/wiki/Code_smell"&gt;code smell&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Type classes and Coherence
&lt;/h4&gt;

&lt;p&gt;Sometimes an application requires multiple implementations for a service. Consider for instance our authentication DSL: Our application may provide authentication against multiple providers, e.g. an LDAP back-end and a user table in a database.&lt;/p&gt;

&lt;p&gt;Consider our authentication DSL. Let’s assume that we want to provide a function to authenticate against multiple back-ends. The obvious solution is to implement a dedicated DSL interpreter for each authentication mechanism:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cats.Monad&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cats.implicits._&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;ch.becompany.Domain.User&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;AuthnService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;:Monad&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                               &lt;span class="n"&gt;authenticators&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;]*)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
      &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
    &lt;span class="nv"&gt;authenticators&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toList&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;collectFirstSomeM&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toOption&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authentication failed"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this is entirely possible using the tagless final pattern, it is only recommended if the DSL is not considered a &lt;a href="https://scalac.io/typeclasses-in-scala/"&gt;type class&lt;/a&gt;. The coherence principle of type classes states that, for each type class &lt;code&gt;Dsl[F[_]]&lt;/code&gt;, there may only be one interpreter for a specific type F in scope. The main goal of coherence is safety: Using different type class interpreters (e.g. different Order interpreters for the Int type) can lead to incorrect programs. Even though Scala doesn't enforce coherence, it is still advisable to keep this principle in mind before providing multiple interpreters for a DSL which is encoded as a type class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modularisation using DSLs
&lt;/h2&gt;

&lt;p&gt;Most programs of a certain complexity can be expressed as a series of layers. The lowest layers deal with technical intricacies and are nowadays usually hidden in third-party libraries. When we move up the stack of layers, technical aspects give way to higher-level functionality that more directly represents the business requirements of our program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Instances at the End of the World
&lt;/h2&gt;

&lt;p&gt;In functional programming, the top-level or &lt;em&gt;main&lt;/em&gt; code block of the application is often referred to as the &lt;em&gt;end of the world&lt;/em&gt;. This is the place where everything happens that cannot be postponed or delegated anywhere else, such as executing side effects or instantiating DSLs. Program code should usually never create a DSL instance, but always consume it as a dependency. This way, the client code (ultimately the main block or test case) has the freedom to provide the desired implementations. Furthermore, if a DSL instance requires an expressive dependency à la &lt;code&gt;cats.effect.Sync&lt;/code&gt;, passing the instance instead of the dependency limits the power of the enclosing module. Compare for instance the following functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Sync&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                       &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// requires Sync&lt;/span&gt;
  &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;interpreter&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; 
  &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
  &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first example could potentially suspend arbitrary side effects in &lt;code&gt;F&lt;/code&gt; and is therefore, judged solely based on its signature, much less predictable than the second example. Furthermore, since it hard-codes the DSL implementation, it cannot be used in conjunction with other &lt;code&gt;AuthnDsl&lt;/code&gt; interpreters, such as mocks.&lt;/p&gt;

&lt;p&gt;Another benefit of creating a DSL instance at the end of the world, i.e. in a single place, is the guarantee that the same implementation is being used throughout the complete application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimize DSL Scope
&lt;/h2&gt;

&lt;p&gt;When modularizing a program using DSLs, each DSL should ideally only address a single concern. This principle is congruent with the &lt;a href="https://homepage.cs.uri.edu/~thenry/resources/unix_art/ch01s06.html"&gt;Unix philosophy&lt;/a&gt; — make each program (or in our case, DSL) do one thing well. Minimizing the scope of DSLs means that code which uses it can wield less power. Furthermore, implementations generally require fewer dependencies, which improves code safety and predictability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contain Dangerous Dependencies
&lt;/h2&gt;

&lt;p&gt;As we have mentioned before, some dependencies are particularly expressive and therefore powerful. One prominent category are those which can be used to suspend arbitrary side effects, such as &lt;code&gt;Sync&lt;/code&gt;, &lt;code&gt;Async&lt;/code&gt; or &lt;code&gt;IO&lt;/code&gt; from the cats-effect library. A code unit which has access to these dependencies wields virtually limitless power and is therefore unpredictable. As a consequence, it is desirable to limit the usage of these dependencies, if possible to the &lt;em&gt;main&lt;/em&gt; block of the application.&lt;/p&gt;

&lt;p&gt;Ideally, only the lowest-level technical DSLs which directly rely on side effects like I/O should be given the power of suspending arbitrary effects. If at one point you find yourself in a situation where you require access to Sync or a similar class, think about whether it would be appropriate to factor out the operation into a dedicated low-level DSL, and instantiate it at the &lt;em&gt;end of the world&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  DSL vs. Service
&lt;/h2&gt;

&lt;p&gt;When should you implement a DSL, and when is it better to use a plain object (which we will call a &lt;em&gt;service&lt;/em&gt;) to group a set of related functions? As we have already discussed, one reason to introduce a DSL is to hide precarious implementation dependencies such as cats.effect.Sync. Another purpose is to provide polymorphic modules, i.e. modules that have different implementations for different types – or, in some cases, can even have multiple implementations for a single type.&lt;/p&gt;

&lt;p&gt;A DSL has a key drawback compared to a service: Each interpreter of the DSL has to implement every function of the DSL. All functions of the interpreter share a single set of constraints — the constraints declared by the function producing the interpreter. If some function implementations don’t use all of these constraints, these functions are technically overconstrained.&lt;/p&gt;

&lt;p&gt;Because of the drawback mentioned above, only polymorphic functions — i.e. those which require different implementations in different interpreters — should be declared in the DSL. Everything else can be provided by a service object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Handling
&lt;/h2&gt;

&lt;p&gt;When it comes to error handling and propagation, there are basically two choices: Declaring the error channel in the signatures of the DSL functions, or using a constraint.&lt;/p&gt;

&lt;p&gt;The first approach is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                   &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Error&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option is particularly useful if the client code of the function is expected to be interested in any potential errors and to be able to handle them appropriately. This certainly applies to an authentication failure.&lt;/p&gt;

&lt;p&gt;With the second approach, the declaration of the DSL doesn’t concern itself with error propagation and leaves this subject to the interpreter. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authorize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Role&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;AuthnDsl&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;interpreter&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;MonadError&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Throwable&lt;/span&gt;, &lt;span class="kt"&gt;?&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the implementation declares a &lt;code&gt;MonadError&lt;/code&gt; constraint, which means that the instance of the type &lt;code&gt;F&lt;/code&gt; is expected to provide an error handling mechanism for a specific error type, in this case &lt;code&gt;Throwable&lt;/code&gt;. This approach makes sense for errors which probably can't be handled by the client code and have to be propagated, sometimes even to the &lt;em&gt;end of the world&lt;/em&gt;. In our example this would for instance be a network communication error occurring when accessing an LDAP server. As mentioned in the previous section, this approach results in overconstraining in case some of the DSL members require error handling and others don't, an implication to keep in mind when designing your DSLs.&lt;/p&gt;

&lt;p&gt;Of course both approaches can be combined, e.g. using an error channel in the return type for business errors and an implementation constraint for low-level technical errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  DSLs for Common Side Effects
&lt;/h2&gt;

&lt;p&gt;As we have learned earlier, having direct access to low-level type classes for expressing side effects — like &lt;code&gt;cats.effect.Sync&lt;/code&gt; – is potentially dangerous. For this reason it is advisable to provide (or use existing) DSLs for frequently used effectful functionality like &lt;a href="https://christopherdavenport.github.io/log4cats/"&gt;logging&lt;/a&gt; or generating timestamps and &lt;a href="https://christopherdavenport.github.io/fuuid/"&gt;UUIDs&lt;/a&gt;. It is also worth considering concealing functions from third-party libraries requiring expressive dependencies, such as &lt;a href="https://http4s.org/"&gt;http4s&lt;/a&gt;, behind façade DSLs to avoid leaking Sync &amp;amp; friends into the codebase.&lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations
&lt;/h1&gt;

&lt;p&gt;I came across a couple of limitations which I haven’t found any solutions or workarounds for. Please don’t hesitate to provide your insights in the comment section.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is not possible to abstract over a set of constraints — each function has to declare the complete set independently.&lt;/li&gt;
&lt;li&gt;It is not possible to identify any unused constraints in IntelliJ IDEA, a circumstance particularly problematic since unused constraints implicate overconstraining and are therefore a code smell. Scala 2.13 provides the compiler option -Wunused:implicits, but I haven't tried it yet and I don't know whether it works with context bounds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Open Source Libraries
&lt;/h1&gt;

&lt;p&gt;Here is a list of some freely available libraries for the cats-effect ecosystem. Some of them provide DSLs directly, others have to be wrapped in a DSL to be used with the tagless final pattern.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/typelevel/cats-tagless"&gt;cats-tagless&lt;/a&gt; — Transform and compose tagless final encoded algebras&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://christopherdavenport.github.io/log4cats/"&gt;log4cats&lt;/a&gt; — Logging (&lt;a href="https://github.com/ChristopherDavenport/log4cats/blob/master/core/shared/src/main/scala/io/chrisdavenport/log4cats/Logger.scala"&gt;Logger DSL&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://christopherdavenport.github.io/fuuid/"&gt;fuuid&lt;/a&gt; — Generating UUIDs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/pureconfig/pureconfig"&gt;pureconfig&lt;/a&gt; — Loading configuration files&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tpolecat.github.io/doobie/"&gt;doobie&lt;/a&gt; — Database access&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://http4s.org/"&gt;http4s&lt;/a&gt; — HTTP (&lt;a href="https://github.com/http4s/http4s/blob/master/client/src/main/scala/org/http4s/client/Client.scala"&gt;Client DSL&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://47deg.github.io/fetch/"&gt;fetch&lt;/a&gt; — Data access&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Final Words
&lt;/h1&gt;

&lt;p&gt;Despite its shortcomings, I believe that tagless final is a valuable addition to the toolbox of the functional Scala programmer. I hope this article contained some helpful advice. I would be very happy to hear about your experience with tagless final — please feel free to use the comment section to let us know about your thoughts, insights and additional best practices. Thank you very much for reading!&lt;/p&gt;




&lt;p&gt;Cover image: &lt;a href="https://unsplash.com/photos/qvBYnMuNJ9A"&gt;Photo&lt;/a&gt; by &lt;a href="https://unsplash.com/@jramos10"&gt;Josue Isai Ramos Figueroa&lt;/a&gt; on Unsplash&lt;/p&gt;

</description>
      <category>programming</category>
      <category>functional</category>
      <category>taglessfinal</category>
      <category>scala</category>
    </item>
    <item>
      <title>Structuring Functional Programs with Tagless Final</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Thu, 28 Mar 2019 12:08:40 +0000</pubDate>
      <link>https://dev.to/devkat/structuring-functional-programs-with-tagless-final-290a</link>
      <guid>https://dev.to/devkat/structuring-functional-programs-with-tagless-final-290a</guid>
      <description>&lt;h4&gt;
  
  
  Monads are valuable tools for handling various concerns in functional programs. In this article we show how domain-specific languages and the Tagless Final pattern can be utilised to build modular monadic programs.
&lt;/h4&gt;

&lt;h1&gt;
  
  
  Domain-Specific Languages and Interpreters
&lt;/h1&gt;

&lt;p&gt;Domain-specific languages (DSLs) are a popular approach for modularising functional programs. A DSL is a set of functions which address a particular concern — this can be anything from an interface to a subsystem to cross-cutting concerns like logging. DSLs are usually layered, i.e. high-level DSLs (for expressing business processes) are built on top of lower-level DSLs (for accessing databases or connecting to remote APIs). In functional programming, DSLs are often called algebras, hinting at the concept’s origin in category theory.&lt;/p&gt;

&lt;p&gt;If you are familiar with object-oriented programming, you can consider a DSL an analogy to an interface: The DSL defines the capabilities of a software module, without providing a concrete implementation. In functional programming, the implementation of the DSL is called an &lt;em&gt;interpreter&lt;/em&gt;. An interpreter implements each function of the DSL.&lt;/p&gt;

&lt;h1&gt;
  
  
  Monads and Separation of Concerns
&lt;/h1&gt;

&lt;p&gt;As outlined in the blog post &lt;a href="https://www.becompany.ch/en/blog/2016/11/08/coooking-with-monads.html"&gt;Cooking with Monads&lt;/a&gt;, monads provide a way of structuring functional programs. In functional programming, we often use monads to explicitly handle certain aspects (“concerns”) of our program without having to express this aspect in the program code itself. Monads allow us to isolate specific concerns from our business logic, which leads to a better &lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separation of concerns&lt;/a&gt; in our programs.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Reader monad allows to pass a context, for instance a configuration, which all computation steps can access.&lt;/li&gt;
&lt;li&gt;The State monad passes state information from one call to the next without the need for mutable data structures in our program code.&lt;/li&gt;
&lt;li&gt;The Task monad provides a way to deal with concurrency, side effects and potential errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these monads support us in relieving the business logic from some of the responsibility of dealing with the respective concerns.&lt;/p&gt;

&lt;h1&gt;
  
  
  Monadic DSLs and Tagless Final
&lt;/h1&gt;

&lt;p&gt;In Scala, the individual functions of a DSL typically have monadic return values, which has the benefit that programs can be written as for-comprehensions. The Tagless Final pattern provides a way to declare a DSL in a generic way, without specifying a particular monad. Multiple interpreters can exist for a DSL, every one potentially targeting a different monad.&lt;/p&gt;

&lt;p&gt;This approach has various benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When writing a program based on Tagless Final DSLs, the target monad of the program can be changed in the future. This way, new features like parallel computation can be introduced without modifying the program itself.&lt;/li&gt;
&lt;li&gt;The DSL can be used with different interpreters. A typical use case is providing an alternative interpreter for testing purposes, using a local data store instead of accessing an external system.&lt;/li&gt;
&lt;li&gt;Multiple DSLs can be combined in a single for-comprehension by chosing interpreters for the same target monad.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Our Example
&lt;/h1&gt;

&lt;p&gt;In our example code we will model a DSL called authn which provides functions for registering and authenticating users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
    &lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;RegistrationError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
    &lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you’re wondering, String @@ EmailAddress is a &lt;a href="http://www.vlachjosef.com/tagged-types-introduction/"&gt;tagged type&lt;/a&gt;, denoting that email is a string with the sole purpose of modelling an e-mail address.&lt;/p&gt;

&lt;p&gt;You find the &lt;a href="https://github.com/becompany/tagless-final-example"&gt;source code&lt;/a&gt; for the example application on GitHub.&lt;/p&gt;

&lt;p&gt;The package structure looks as follows. We are coupling our code based on &lt;a href="https://en.wikipedia.org/wiki/Functional_design"&gt;functional design&lt;/a&gt;, meaning that code with common functionality goes in the same package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ch.becompany
  authn           Authentication functionality
    domain        Authentication domain code
    Dsl           Authentication DSL
  shapelessext    Extensions to the shapeless library
  shared          Shared code
    domain        Shared domain code
  Main.scala      Our main application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the example, execute the following command in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sbt run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modeling DSLs with Tagless Final
&lt;/h3&gt;

&lt;p&gt;In the Tagless Final pattern, a DSL is modelled as a trait with a single type parameter, which has to be a type constructor with arity 1. We will call this type constructor &lt;code&gt;F[_]&lt;/code&gt;. At this moment, it's actually not required that F is a monad. Later on, when implementing an interpreter for our DSL, the target monad of the interpreter will take the place of F.&lt;/p&gt;

&lt;p&gt;Let’s model our authentication DSL in this style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;ch.becompany.authn&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
      &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;RegistrationError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
      &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the return values of all DSL functions are wrapped in the container F. In the following program, the compiler infers the type parameter F[_] from the return type of the registerAndLogin function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;ch.becompany&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerAndLogin&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;authnDsl&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
      &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;email&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"john@doe.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;password&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"swordfish"&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;authenticated&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function signature ensures that F is a monad (by requiring the existence of an implicit value of the type Monad[F]). Therefore the functions of our DSL can be used in for-comprehensions. Even at this stage, we don't specify a concrete type for F; the registerAndLogin function could actually be part of a higher-level DSL.&lt;/p&gt;

&lt;p&gt;Besides the Monad instance, the function requires an additional parameter: An instance for the authentication DSL (also called an &lt;em&gt;interpreter&lt;/em&gt;), typed with the common type F. The parameter is declared as implicit to allow automatic resolution by the compiler; we will look into this in detail when we talk about interpreters.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interpreters
&lt;/h1&gt;

&lt;p&gt;Now that we have defined the syntax of our DSL in the respective trait, we have to implement the semantics. With the Tagless Final technique, this is done in an &lt;em&gt;interpreter&lt;/em&gt;. For each DSL, multiple interpreters can exist; each of them targeting a specific type. Interpreters are typically modelled as &lt;a href="http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html"&gt;type classes&lt;/a&gt;, so they can be automatically resolved by the compiler when a DSL is used with the respective target type.&lt;/p&gt;

&lt;p&gt;In the beginning we will choose a target type which make it easy to test the concepts in a simple, self-contained program. In a real-world scenario, you would probably follow the same approach: Start with providing easy-to-use interpreters for your DSLs which can be utilised in test cases. This approach is comparable to implementing mocks, with the difference that our interpreter is a full-featured implementation of the DSL.&lt;/p&gt;

&lt;p&gt;Later on we can proceed to implementing interpreters for more sophisticated target types covering additional concerns like concurrency and side-effects.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interpreter for the Authentication DSL
&lt;/h1&gt;

&lt;p&gt;We implement the interpreter in the companion object of the Dsl trait, thereby supporting the implicit resolution mechanism of the compiler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;ch.becompany.authn&lt;/span&gt;

&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepository&lt;/span&gt;, &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;StateInterpreter&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

     &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
         &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;RegistrationError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
       &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
         &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
           &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RegistrationError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User already exists"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;asLeft&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;:+&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asRight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;

     &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
         &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
       &lt;span class="nv"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;
         &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;find&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;password&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthnError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authentication failed"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to store the registered users in a list, so our UserRepository type is a simple list of users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will utilise the &lt;a href="https://typelevel.org/cats/datatypes/state.html"&gt;State&lt;/a&gt; monad for passing the user repository from one DSL function call to the next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepository&lt;/span&gt;, &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we define the StateInterpreter, an interpreter for the authentication DSL targeting the UserRepositoryState monad. Note that the object is declared with the implicit modifier, which makes it visible to the compiler when a DSL interpreter for this target type is requested.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;StateInterpreter&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Dsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
       &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;RegistrationError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
     &lt;span class="nc"&gt;State&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
       &lt;span class="nf"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
         &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;RegistrationError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"User already exists"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;asLeft&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
         &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;:+&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asRight&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;@@&lt;/span&gt; &lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
       &lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
     &lt;span class="nv"&gt;State&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;
       &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;find&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;password&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
       &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toRight&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthnError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authentication failed"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Running the Program
&lt;/h1&gt;

&lt;p&gt;Now that we have provided an interpreter for our DSL, we can execute the registerAndLogin program which we have implemented in our Main application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;ch.becompany&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;registerAndLogin&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;authnDsl&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AuthnDsl&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
      &lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AuthnError&lt;/span&gt;, &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;email&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;EmailAddress&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"john@doe.com"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;password&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"swordfish"&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;register&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;authenticated&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;authnDsl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;authn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;userRepositoryState&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registerAndLogin&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;userRepositoryState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;runEmpty&lt;/span&gt;

  &lt;span class="nf"&gt;val&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;

  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authenticated: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Registered users: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By calling registerAndLogin with the UserRepositoryState type parameter value, we instruct the compiler to resolve the interpreter – declared as the implicit parameter authnDsl – for the UserRepositoryState target monad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;userRepositoryState&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;registerAndLogin&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserRepositoryState&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the runEmpty method to pass an empty list of users as the initial state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;userRepositoryState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;runEmpty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The runEmpty method returns an instance of the Eval monad, whose computation produces a tuple consisting of the final state (in our case the user repository containing all registered users) and the return value of the program (in our case the authentication result). Now we can finally extract these values using the value method of the Eval monad, and print the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nf"&gt;val&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;
  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authenticated: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Registered users: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of our program looks as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentiated: Right(User(john@doe.com,swordfish))
Registered users: List(User(john@doe.com,swordfish))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Next Steps: Combining Multiple DSLs
&lt;/h3&gt;

&lt;p&gt;To support combining calls from different DSLs in a for-comprehension, all of these functions must return their values in the same monad.&lt;/p&gt;

&lt;p&gt;In many cases it is possible to choose a monad which addresses all required concerns, typically side-effects and error handling. Examples are the &lt;a href="http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/"&gt;Task&lt;/a&gt; type from the &lt;a href="https://github.com/scalaz/scalaz"&gt;ScalaZ&lt;/a&gt; library or the &lt;a href="https://typelevel.org/cats-effect/datatypes/io.html"&gt;IO&lt;/a&gt; type from the &lt;a href="https://typelevel.org/cats-effect/"&gt;cats-effect&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;But to find a generic approach to deal with this restriction actually proves to be quite challenging. One possible solution is using Free monads, for example the Eff monad; this approach which will be presented in an upcoming article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Further Reading
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://typelevel.org/blog/2017/12/27/optimizing-final-tagless.html"&gt;Optimizing Tagless Final — Saying farewell to Free&lt;/a&gt; from the Typelevel blog&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.scalac.io/exploring-tagless-final.html"&gt;Exploring Tagless Final pattern for extensive and readable Scala code&lt;/a&gt; from the scalac team blog&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://softwaremill.com/free-tagless-compared-how-not-to-commit-to-monad-too-early/"&gt;Free and tagless compared — how not to commit to a monad too early&lt;/a&gt; by Adam Warski&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.beyondthelines.net/programming/introduction-to-tagless-final/"&gt;Introduction to Tagless final&lt;/a&gt; from the Beyond the Lines blog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you very much for reading! Please leave your comments below, and don’t hesitate to contact me at &lt;a href="//mailto:andreas.hartmann@becompany.ch"&gt;andreas.hartmann@becompany.ch&lt;/a&gt; if you have further questions.&lt;/p&gt;




&lt;p&gt;Cover photo: &lt;a href="https://unsplash.com/photos/erRtgkmFvh4"&gt;Gloucester Cathedral&lt;/a&gt; by &lt;a href="https://unsplash.com/@thenathasja"&gt;Nathasja Vermaning&lt;/a&gt; on Unsplash&lt;/p&gt;

</description>
      <category>scala</category>
      <category>functional</category>
      <category>taglessfinal</category>
    </item>
    <item>
      <title>CSV parsing with Scala and shapeless</title>
      <dc:creator>Andreas Jim</dc:creator>
      <pubDate>Mon, 17 Dec 2018 08:14:48 +0000</pubDate>
      <link>https://dev.to/devkat/csv-parsing-with-scala-and-shapeless-5hho</link>
      <guid>https://dev.to/devkat/csv-parsing-with-scala-and-shapeless-5hho</guid>
      <description>&lt;h4&gt;
  
  
  The &lt;a href="https://github.com/milessabin/shapeless"&gt;shapeless&lt;/a&gt; library serves as an excellent foundation for building generic, reusable components. We demonstrate using the types &lt;code&gt;HList&lt;/code&gt; and &lt;code&gt;Generic&lt;/code&gt; to parse strings into case classes.
&lt;/h4&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This post complements the upcoming article &lt;a href="https://www.becompany.ch/en/blog/2016/07/29/realtime-log-processing"&gt;Real-time log processing with Akka streams&lt;/a&gt;, which involves processing log entries from a web server log. For convenience and clarity, we want to parse the log file line strings into case class instances, allowing us to process them in a semantic fashion.&lt;/p&gt;

&lt;p&gt;There are countless libraries available for parsing strings; we will use &lt;a href="https://github.com/tototoshi/scala-csv"&gt;scala-csv&lt;/a&gt; and &lt;a href="https://github.com/milessabin/shapeless"&gt;shapeless&lt;/a&gt; to demonstrate a generic and extensible approach. Some of the code we use is based on the &lt;a href="https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/csv.scala"&gt;CSV example&lt;/a&gt; in the shapeless codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get the source
&lt;/h3&gt;

&lt;p&gt;The source code of the example project is &lt;a href="https://github.com/becompany/akka-streams-example"&gt;available on github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Log format
&lt;/h3&gt;

&lt;p&gt;Our example uses a web server log format with the following components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Remote IP address&lt;/li&gt;
&lt;li&gt;Time in milliseconds (Unix time stamp)&lt;/li&gt;
&lt;li&gt;Request path&lt;/li&gt;
&lt;li&gt;User agent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This roughly corresponds to the following nginx log configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;log\_format my\_log\_format
  '"$remote\_addr","$msec","$request","$http\_user\_agent"';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A log entry looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"1.2.3.4","1466585706027","/foo","Chrome"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We will use the following case class to represent log events:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Parsing string values into objects
&lt;/h3&gt;

&lt;p&gt;A parser type for individual CSV record elements is defined by the &lt;a href="https://github.com/becompany/akka-streams-example/blob/master/src/main/scala/ch/becompany/akka/io/csv/Parser.scala"&gt;&lt;code&gt;Parser&lt;/code&gt;&lt;/a&gt; trait. The parse result is either an object of type &lt;code&gt;T&lt;/code&gt; or an error message:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For convenience, we provide a parser which handles exceptions and returns an error message. This covers the typical scenario of using parser methods from Java libraries, e.g. &lt;code&gt;Integer.parseInt&lt;/code&gt;, which throws &lt;code&gt;NumberFormatException&lt;/code&gt;, or &lt;code&gt;DateFormat.parse&lt;/code&gt;, which throws &lt;code&gt;ParseException&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;a href="https://github.com/becompany/akka-streams-example/blob/master/src/main/scala/ch/becompany/akka/io/csv/Parser.scala"&gt;&lt;code&gt;Parsers&lt;/code&gt;&lt;/a&gt; object provides a trivial parser for strings. The client application can provide additional custom parsers. Our application provides a parser for parsing millisecond expressions into Joda Time &lt;code&gt;Instant&lt;/code&gt; objects and a parser for IP addresses:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Parsing CSV records
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/becompany/akka-streams-example/blob/master/src/main/scala/ch/becompany/akka/io/csv/LineParser.scala"&gt;&lt;code&gt;LineParser[T]&lt;/code&gt;&lt;/a&gt; class parses a CSV record, which is represented as a &lt;code&gt;List[String]&lt;/code&gt;, into an instance of case class &lt;code&gt;T&lt;/code&gt;. We use the &lt;code&gt;HList&lt;/code&gt; (heterogenous list) type from the shapeless library to express the types of the list elements. The string list is first converted to a &lt;code&gt;HList&lt;/code&gt; instance, which in turn is converted to a case class instance.&lt;/p&gt;

&lt;p&gt;We will need some types from the shapeless library:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First we define a &lt;code&gt;LineParser[Out]&lt;/code&gt; trait which defines the capability of parsing a list of strings into an object of type Out. In the case of an error, we expect that the parsing errors of individual list elements will be aggregated into a list represented by the Left incarnation of the &lt;code&gt;Either&lt;/code&gt; result type.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now we define a companion object for our &lt;code&gt;LineParser&lt;/code&gt; trait which provides methods for parsing &lt;code&gt;List[String]&lt;/code&gt; instances into &lt;code&gt;HList&lt;/code&gt; instances. The methods are declared as implicit, making them available in the &lt;code&gt;LineParser&lt;/code&gt;trait. The object provides a method for each of the &lt;code&gt;List&lt;/code&gt; incarnations &lt;code&gt;Nil&lt;/code&gt; and &lt;code&gt;Cons&lt;/code&gt; (&lt;code&gt;::&lt;/code&gt;, although we are using &lt;code&gt;+:&lt;/code&gt; due to a name collision with the shapeless &lt;code&gt;::&lt;/code&gt; type).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;hnilParser&lt;/code&gt; method is expected to emit an empty list and returns an error if it encounters a list containing one or multiple elements:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;hconsParser&lt;/code&gt; method parses a concatenation of a head element (type &lt;code&gt;H&lt;/code&gt;) and a tail list (type &lt;code&gt;T&lt;/code&gt;) while combining the errors which may occur during the parsing steps accordingly. Note the &lt;code&gt;Parser&lt;/code&gt; type tag for the &lt;code&gt;H&lt;/code&gt; type which ensures that the list element type &lt;code&gt;H&lt;/code&gt; is a member of the &lt;code&gt;Parser&lt;/code&gt; type class, i.e. that a parser for this type is provided. The parser is later on obtained using the expression &lt;code&gt;implicitly[Parser[H]]&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The following implicit method converts the &lt;code&gt;HList&lt;/code&gt; &lt;code&gt;R&lt;/code&gt; into the case class &lt;code&gt;A&lt;/code&gt;, using the shapeless &lt;code&gt;Generic&lt;/code&gt; type. We define an implicit parameter gen, whose type is an instance of the &lt;code&gt;Generic&lt;/code&gt; trait with a representation of type &lt;code&gt;R&lt;/code&gt;. The method call &lt;code&gt;gen.from&lt;/code&gt; converts the &lt;code&gt;HList&lt;/code&gt; representation into the desired instance of case class &lt;code&gt;R&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;apply[A]&lt;/code&gt; method is parameterised with the type of the expected case class. It uses the implicitly provided parser to parse the list elements. The implicitly available method &lt;code&gt;caseClassParser&lt;/code&gt; allows us to use a case class as the type parameter for the apply method.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Putting it all together
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/becompany/akka-streams-example/blob/master/src/main/scala/ch/becompany/akka/io/csv/Csv.scala"&gt;&lt;code&gt;CsvReader[T]&lt;/code&gt;&lt;/a&gt; class converts comma-separated strings into objects of type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The read method parses the lines of an Akka stream source, which emits elements of type String, into objects of type &lt;code&gt;T&lt;/code&gt;. Note that the type parameter &lt;code&gt;T&lt;/code&gt; has a context bound of type &lt;code&gt;LineParser&lt;/code&gt;, which ensures that a parser is available for this type, as explained in the previous section.&lt;/p&gt;

&lt;p&gt;The class uses the CSV parser class from the scala-csv library to split lines into lists of strings. In case the line was successfully split into a list of strings, a &lt;code&gt;LineParser[T]&lt;/code&gt; is created and its apply method is invoked on the string list.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;CsvReader[T].read&lt;/code&gt; method can now be used to transform a source of strings into a source of elements of type &lt;code&gt;T&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  Further reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://meta.plasm.us/posts/2015/11/08/type-classes-and-generic-derivation/"&gt;Type classes and generic derivation&lt;/a&gt; on meta.plasm.us&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/milessabin/shapeless"&gt;shapeless&lt;/a&gt; on github&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tototoshi/scala-csv"&gt;scala-csv&lt;/a&gt; on github&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This article was originally published on the&lt;/em&gt; &lt;a href="https://www.becompany.ch/en/blog/2016/07/13/csv-parsing"&gt;&lt;em&gt;BeCompany blog&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>akkastreams</category>
      <category>shapeless</category>
      <category>scala</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
