<?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>Forem: Zelenya</title>
    <description>The latest articles on Forem by Zelenya (@zelenya).</description>
    <link>https://forem.com/zelenya</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%2F1016278%2Ffb70f3cf-5b0d-45da-9648-9cf1f09342f5.jpg</url>
      <title>Forem: Zelenya</title>
      <link>https://forem.com/zelenya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zelenya"/>
    <language>en</language>
    <item>
      <title>Types and Compilers are our friends</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Mon, 30 Mar 2026 03:19:47 +0000</pubDate>
      <link>https://forem.com/zelenya/types-and-compilers-are-our-friends-3h77</link>
      <guid>https://forem.com/zelenya/types-and-compilers-are-our-friends-3h77</guid>
      <description>&lt;p&gt;The (natural) language we use is influenced by how we feel and what we think, but it also works the other way: just by the way we approach things, we can make our experience better or worse.&lt;/p&gt;

&lt;p&gt;So, when we say "compiler is in the way" or "I have to fight the compiler", we are setting ourselves up for failure. And I don't mean some gigantic failures ‒ I mean small shitty every-day frustrations. There is no need to live like this.&lt;/p&gt;

&lt;p&gt;And it's normal to be frustrated, not trying to put pink glasses on everyone, just trying to share &lt;em&gt;different&lt;/em&gt; perspectives on &lt;em&gt;some&lt;/em&gt; things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good and Bad
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I don't want to go too deep into details or muddy the definitions. Let's establish an abstraction level: we'll focus on moving more work &lt;strong&gt;out of runtime&lt;/strong&gt; to build/compilation time.&lt;/p&gt;

&lt;p&gt;We don't have to search too long to get to the most common arguments on this topic:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Good"&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;catching bugs&lt;/li&gt;
&lt;li&gt;enforcing correctness&lt;/li&gt;
&lt;li&gt;improving performance (optimizations)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;"Bad"&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;introducing "to-live" latency (slow)&lt;/li&gt;
&lt;li&gt;introducing cryptic error messages&lt;/li&gt;
&lt;li&gt;introducing unnecessary work (bad for prototyping)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's somewhat common to treat those as trade-offs. Some people say that those &lt;em&gt;"bads"/"frustrations"&lt;/em&gt; are there because the compilers are doing solid work for us. Others say it's not worth it. And we keep going in circles for years. &lt;/p&gt;

&lt;p&gt;There is some truth to that. However, I don't think of those as "frustrations" nor as balanced trade-offs. And here's why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bad? Introducing latency
&lt;/h2&gt;

&lt;p&gt;Things are relative. Slowness is relative. When we want to run a program and check our changes, there is a difference between waiting for javascript, purescript, and scala to run. Okay. &lt;/p&gt;

&lt;p&gt;However, when we account for the time it takes bugs (or programming errors) to surface, we see a more noticeable difference.&lt;/p&gt;

&lt;p&gt;For example, imagine we added a new status to a reporting job: "dismissed", ran the program (or even deployed it), opened the dashboard, updated the state, checked that it's there, and were done. Pretty sure this could be accomplished with javascript xTimes faster than with scala. Ok, but. If this status is used somewhere else, we didn't notice, javascript didn't care, and as a result, our users faced the bug. Not ok.&lt;/p&gt;

&lt;p&gt;We traded off waiting seconds for the compiler to verify that all enum usages are exhaustive for a runtime error hours later. Was it worth it? Still valid to ask and question that.&lt;/p&gt;

&lt;p&gt;And yes, compilation times can be really slow, but there is often room for improvement. And I don't mean just waiting for the compiler team to do the improvements ‒ I mean rolling up our sleeves. I know it's nice to have things out of the box, but if you want faster builds, you &lt;em&gt;might&lt;/em&gt; need to do something yourself: reorganize modules for incremental-friendly compilation, figure out the optimal build configurations, tweak the CI caches, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bad? Introducing error messages
&lt;/h2&gt;

&lt;p&gt;Similar situation with error messages. &lt;/p&gt;

&lt;p&gt;There is elm with friendly compilation error messages, haskell with infamous messages, and then there are null pointer exceptions at runtime. I don't know about you, but I'd take an unknown to me haskell compilation error message over a vague null pointer runtime exception any time.&lt;/p&gt;

&lt;p&gt;And let's face it: If I see a compilation error, it means I made an error. It's not the compiler's fault (at least most of the time). And it's okay to make mistakes during development, it's a great time to make mistakes – we can learn from those! Look at this beautiful error: &lt;a href="https://doc.rust-lang.org/stable/error_codes/E0507.html" rel="noopener noreferrer"&gt;E0507&lt;/a&gt;. We can read it like a book.&lt;/p&gt;

&lt;p&gt;Not all errors are the same. Not sure we can learn much from the compiler telling us that we forgot a semicolon. &lt;em&gt;If you are so smart, Java, why don't you put a semicolon there yourself?!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And of course, individual error messages can and should be improved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good. Catching bugs
&lt;/h2&gt;

&lt;p&gt;Remember how we talked about adding a new status to a reporting job?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;InProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Failed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Dismissed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Show pattern matching error&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InProgress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nn"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;InProgress&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not done"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// error[E0004]: non-exhaustive patterns: `Status::Failed` and `Status::Dismissed` not covered&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are incredibly useful when we need to express constraints on the values. But we need support from a compiler (to properly create, pass, and consume those). &lt;/p&gt;

&lt;p&gt;Also, I'm not saying the compiler is good; no compiler is bad. I want to paint a picture around expectations and intentions. For instance, the go compiler has a weak offering for the status. We can fake enums / sum types, but it's still quite error-prone; for example, nobody warns us if a case in a switch is missing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;InProgress&lt;/span&gt; &lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;iota&lt;/span&gt;
    &lt;span class="n"&gt;Done&lt;/span&gt;
    &lt;span class="n"&gt;Failed&lt;/span&gt;
    &lt;span class="n"&gt;Dismissed&lt;/span&gt;
&lt;span class="p"&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 go"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;InProgress&lt;/span&gt;

&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Done"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;InProgress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not done"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// No complaints&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Let's look at another example.&lt;/p&gt;

&lt;p&gt;Rust has a single-threaded-only primitive &lt;a href="https://docs.rs/rustc-std-workspace-std/latest/std/rc/struct.Rc.html" rel="noopener noreferrer"&gt;&lt;code&gt;Rc&lt;/code&gt;&lt;/a&gt; (in other words, it's not thread-safe). If we try to use it concurrently, the compiler won't let us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Rc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ERROR: `Rc&amp;lt;i32&amp;gt;` cannot be sent between threads safely&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value = {value}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler refuses to let the value cross a thread boundary before the program ever runs (through the &lt;code&gt;Send&lt;/code&gt; trait). Nothing is stopping us from making those sorts of mistakes in java. For instance, we can forget to use &lt;code&gt;volatile&lt;/code&gt; on a variable (and the changes won't be noticed by other threads), or we can use a non-atomic operation on concurrent collections – we always need to be aware and use the right combination of keywords and primitives.&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;java.util.concurrent.ConcurrentHashMap&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;Main&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="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&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="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ConcurrentHashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// not atomic!&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&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="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// not atomic!&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;});&lt;/span&gt;

        &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&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;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expected: 2000, Got: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"count"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="c1"&gt;// The result is going to be different on each run, not 2000&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 you can use a thread-safe &lt;a href="https://docs.rs/rustc-std-workspace-std/latest/std/sync/struct.Arc.html" rel="noopener noreferrer"&gt;&lt;code&gt;Arc&lt;/code&gt;&lt;/a&gt; there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Arc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;move&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value = {value}"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="nf"&gt;.join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;One can argue for a skill issue or whatever, but we won't go there.&lt;/p&gt;

&lt;p&gt;The rust compiler or type system is quite expressive, allowing us to be quite expressive. We can eliminate classes of bugs, as well as classes of thoughts. We don't have to think about using the wrong collection because it's not even possible. With more thinking capacity, we can prioritize mastering things that actually matter – in writing or review, we can focus on the core intent of the code.&lt;/p&gt;

&lt;p&gt;And it's not about thinking less; sometimes we have to think more. In general, it's about thinking about different things (and at different times). &lt;/p&gt;




&lt;p&gt;I am a big fan of the "parse don't validate" approach. For example, using an explicit &lt;code&gt;non-empty list&lt;/code&gt; instead of normal arrays or lists with comments, runtime errors, or whatever. A non-empty collection isn't always better or a possible alternative to a collection. So, we have to think and decide upfront if enforcing a non-empty requirement is actually the right thing to do (depends on what and for whom we are optimizing). But if we do decide, someone can't mess it up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Please pass a non-empty array, please!&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
  &lt;span class="kt"&gt;Nothing&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;throwException&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="s"&gt;"Unexpected empty array"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;x&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 haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;NonEmptyArray&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, imagine: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have a giant list (or text) that we need to carry around and render in multiple places in our system. &lt;/li&gt;
&lt;li&gt;In some places, we want to show it raw, in others – sorted. &lt;/li&gt;
&lt;li&gt;Showing the wrong thing in the wrong place is bad, and sorting is expensive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can express this with types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RawText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SortedText&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RawText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ActionA&lt;/span&gt;

&lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;SortedText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ActionB&lt;/span&gt; 

&lt;span class="n"&gt;baz&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RawText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SortedText&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ActionC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, we can never mess it up (never mix things up, never forget to sort, and never sort twice). In languages like haskell and rust, those safety nets are zero-cost abstractions. Compilers take care of those – they don't appear at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good. Improving performance
&lt;/h2&gt;

&lt;p&gt;When it comes to optimizations, it's rarely as simple as Y times slower compilation = Z times faster runtime. Regardless, compilers are often aware of things that we're not thinking about or are too lazy to think about. So, why not let them assist us?&lt;/p&gt;

&lt;p&gt;Take, for instance, &lt;a href="https://react.dev/learn/react-compiler" rel="noopener noreferrer"&gt;react compiler&lt;/a&gt;. &lt;em&gt;Probably not the first association that comes to mind when we talk about compilers, but it's a good illustration&lt;/em&gt;. This build-time tool automatically optimizes the application by handling memoization (adding useCallback, useMemo, useRef, and other tweaks and optimizations in the right places), so we don't need to worry about them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...freeing you from this mental burden so you can focus on building features."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once again, back to freeing our thinking. And, just to be clear, I'm not advocating for thoughtless development – we need to be realistic about management of our thinking resources. Of course, we lose some control. What if we add a minute to the build for a 100ms rendering improvement for the users? Is this a fair tradeoff? &lt;/p&gt;

&lt;h2&gt;
  
  
  Bad for prototyping?
&lt;/h2&gt;

&lt;p&gt;Out of all of these, the meme about prototypes gets on my nerves the most. &lt;/p&gt;

&lt;p&gt;First, short term vs long term effects of prototypes. Why does nobody talk about the long term? Why can't we admit that most prototypes stay in production? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prototypes are products. &lt;/li&gt;
&lt;li&gt;The impact of failure is high.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;I know why, because it requires introspection and admitting mistakes, nobody wants to do that...&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;After seeing dozens or hundreds of prototypes, I'm pretty confident that languages with fearless refactoring shine here. Haskell, PureScript, etc. are really good when it comes to delivering with rapidly changing requirements while staying reasonably correct and maintainable.&lt;/p&gt;

&lt;p&gt;Rust is not famous for its refactoring – the meme is that if you choose the wrong abstraction, you have to rewire everything. However, even then, I'd still take refactoring a project in rust over javascript 9 times out of 10.&lt;/p&gt;




&lt;p&gt;Ok, let's take a step back and simplify to the short term. Let's imagine an extreme example: 1 out of 10 experiments actually stays. Or even, 1 out of 10 one-off scripts doesn't get thrown away the next day. In this case, ok, I agree, we don't need anything maintainable. The impact of failure is low.&lt;/p&gt;

&lt;p&gt;However, it's still a myth that something like python is the best for this. It still 100% depends on the individual or team experience. I think throw-away scripts are the best proof. I've seen people do those in bash, python, scala, rust, typescript... &lt;em&gt;I can keep going.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If a person is good at something, they will be good at it when they need something fast.&lt;/p&gt;

&lt;p&gt;Sure, we can kickstart a blog on rails xTimes faster than in haskell (from scratch). But we are not making hello worlds. What is this metric? If I'm in a company that has 20 production projects in haskell, and 0 in ruby, I bet it would be much faster to start the 21st one in haskell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hold on, what about tests and linters?
&lt;/h2&gt;

&lt;p&gt;The initial abstraction is a bit leaky. We included the "react compiler" build tool, but I want to push back on some other build tools. A bit. It's somewhat common to hear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We don't need proper type systems, we write tests and catch things with linters."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Both are the wrong tools for that job. Simple as that. Those also add latency, vague errors, and unnecessary work. And, on top of that, they are more error-prone, add flakiness, increase the size of the codebase, and are easy to neglect (or forget).&lt;/p&gt;

&lt;p&gt;I use linters and tests a lot, and they are important. But as supplemental tools. It's like real supplements. Compare eating junk food along with taking a bunch of multivitamins vs. eating nutritious food and a couple of vitamins you personally need.&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Pnu7dXOAaQU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>functional</category>
      <category>rust</category>
    </item>
    <item>
      <title>Is this our last chance to use fun programming languages at work?</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Sun, 15 Feb 2026 19:44:22 +0000</pubDate>
      <link>https://forem.com/zelenya/is-this-our-last-chance-to-use-fun-programming-languages-at-work-2hf1</link>
      <guid>https://forem.com/zelenya/is-this-our-last-chance-to-use-fun-programming-languages-at-work-2hf1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Do you care what programming language to use?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I often think about reddit discussions, where someone genuinely asks how they can find a Haskell job, for example, and there are always people who advise against looking for a job based on the language (instead of answering the original question). I get it. I understand arguments for both sides, but I won't argue for either. Some care 80% of the time, some don't care 80% of the time.&lt;/p&gt;

&lt;p&gt;A different way to look at this is from the perspective of mainstream vs niche programming languages. Because if you are obsessed with a programming language, you are likely obsessed with some niche, esoteric language. And if you are not obsessed, you are probably using something more or less standard; the good old "nobody ever got fired for choosing Oracle".&lt;/p&gt;

&lt;p&gt;Those aren't the same, but bear with me. I'll repeat myself, not arguing for any side, I want to establish that there is a conflict: within a team, a company, a wider industry, wherever. There are people with different values and interests.&lt;/p&gt;

&lt;p&gt;Another &lt;strong&gt;very new conflict&lt;/strong&gt; is about the use of LLMs. Once again, some people are all about it, some refuse to use it, and all sorts of in-between.&lt;/p&gt;

&lt;p&gt;If we overlap those, we get conflicting quadrants. It’s a simple illustration ‒ conflicts are rarely two-dimensional. But conflicts are not fun. Sure, some people love conflicts and thrive in conflicts, but for normal people, constant conflicts are not fun. If most people on my team are in one quadrant and I'm in another, I have to deal with it: either suppress my needs, argue, change companies, or whatever.&lt;/p&gt;

&lt;p&gt;I've been thinking about this, and while I was looking at a project at work, it clicked: we can have our cake and eat it too (one group can have it and another can eat it). We can have successful and less-conflict teams over multiple quadrants.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furrufvnzdfsla8gdi0g0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furrufvnzdfsla8gdi0g0.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I'll tell you the story about this little project, and maybe it can give you hope or inspiration in some dark, turbulent times.&lt;/p&gt;

&lt;h2&gt;
  
  
  A story about a little project
&lt;/h2&gt;

&lt;p&gt;About 2 years ago, I wanted to migrate an existing internal dashboard to PureScript. The existing one was part of the legacy system that nobody wanted to touch, let alone extend. So the bar was quite low. &lt;/p&gt;

&lt;p&gt;My goals were to 1) quickly migrate basic functionality to unblock the migration of a larger legacy system, which was driving me crazy, 2) make it composable and extendable with the lowest possible friction: have copy-pasteable components and allow people to integrate TypeScript and JavaScript components easily, 3) showcase PureScript and get people curious (spoiler, this didn't bear fruit). &lt;/p&gt;

&lt;p&gt;It was never &lt;strong&gt;a goal&lt;/strong&gt; to spread the PureScript usage; the arrangement with a team and tech leadership was to give it a try for a few of weeks, and then consider or plan a rewrite to TypeScript. I did an mvp (including the migration of core functionality) in my free time because there was no time for that during work hours. As a plus, I got a video about PureScript+shadcn/ui and a template out of it. &lt;/p&gt;

&lt;p&gt;I believe one of the worst, unprofessional stunts that one can do is to introduce something that nobody can maintain. It can soil the reputation of the thing forever. I had an experience where someone used Haskell for a project, which had terrible management and plans from the beginning ‒ it was doomed to fail. Because it sucked, people quit. Eventually, nobody could or wanted to maintain it. Guess who was a scapegoat? Years later, people who don't even know what Haskell looks like were blaming it (and the dev team) for everything.&lt;/p&gt;

&lt;p&gt;After I deployed the first version, it was just the two of us contributing. My accomplice had no prior PureScript experience and first hated it: mostly because of the tooling and compilation errors. But, he still contributed more code and functionality than me. And, in a couple of weeks, we got it to a pretty big state. And it wasn't even on our team's priority list; we were doing it in the evenings and between things.&lt;/p&gt;

&lt;p&gt;Things were going pretty well, the project was growing, and then we went from copilot to the llm-assisted coding era. It's really big now. A lot of annoying things that used to be managed manually are now behind this nice ui: a bunch of customer support tools, dev tools, a bunch of product configurations, some analytics, and exploration tools. A huge portion of that code isn't human-written. Quite successful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it works well and what we can learn from this
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why it works in a specific case
&lt;/h3&gt;

&lt;p&gt;One of the main reasons it works (and scales) so well is that it's a stateless app (ofc we persist users' dark/light mode preference), and consists of simple flows. Also, when we let the llms loose, we had a solid project with a bunch of code, a lot of good copy-pasteable code (for what it's worth).&lt;/p&gt;

&lt;p&gt;Each tool doesn't affect the rest. The only problem is organizing everything and not cluttering the ui, but that's more of a fun puzzle than an actual problem. In this context, I'm not afraid of any potentially bad or slow or whatever changes affecting the rest of the tools; there is no need for wild smoke tests or QAs.&lt;/p&gt;

&lt;p&gt;For example, one person wanted to add a new fraud-prevention tool. They aren't part of our team and have never touched PureScript before. We had a five-minute chat, I shared the repository and told them, "Look, as long as there are secure endpoints, there isn't anything else to worry about, really". The project's &lt;a href="https://github.com/Zelenya/purescript-shadcn-tailwind-copypaste?tab=readme-ov-file#tooling-and-setting-things-up" rel="noopener noreferrer"&gt;readme&lt;/a&gt; is just &lt;code&gt;npm install&lt;/code&gt; and &lt;code&gt;npm start&lt;/code&gt;, so don't think that we have something sophisticated going on. They opened a pull request the next day, the code looks pretty good and consistent, and ui looks nice and friendly.&lt;/p&gt;

&lt;p&gt;Which is fun and brings us to the most exciting part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it works despite being functional
&lt;/h3&gt;

&lt;p&gt;There were always concerns with steep learning curves. People bring this up most times someone mentions Haskell, Scala, Rust, or any other non-mainstream language.&lt;/p&gt;

&lt;p&gt;This is no longer a serious argument.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;contribution&lt;/strong&gt; entrance level is pretty low now. I definitely don't want to generalize and pretend like every contribution is equal, that this applies to acquiring proper skills, or anything like that, and I'm also not talking about open source.&lt;/p&gt;

&lt;p&gt;But, in work environments, there are opportunities now to have good human code (I would go as far as to say, good &lt;strong&gt;functional&lt;/strong&gt; code) and open the gates to various contributors. And if you have a higher bar then llms can deliver, you can always refactor and polish the code as needed.&lt;/p&gt;

&lt;p&gt;As a bonus, we can lower the fear of maintainability and bus-factor. Microsoft says they are going to use llms to rewrite everything to Rust, so if somebody out there was brave enough to claim that, surely, we can be brave enough to introduce new technologies at smaller scale. &lt;/p&gt;

&lt;p&gt;If somebody hates your Haskell tool at work, what stops them from rewriting it over the weekend? It has never been easier. I only had experience with migrating Ruby, JavaScript, and Python code to functional languages, but I'm pretty sure it works the other way around.&lt;/p&gt;

&lt;p&gt;And it also extrapolates to making libraries. If someone says: "Oh, no! There is no Haskell SDK for a new hyped technology!" We can just laugh at them and send them back to 2025! &lt;em&gt;Sorry. This is one of my favorite internal jokes.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;In the case of PureScript, we don't even need to rewrite libraries ‒ we can just generate FFIs (PS-friendly bindings) to existing JS/TS libraries. We can also generate TypeScript code that uses those libraries and then generate PS bindings to this code instead...&lt;/p&gt;

&lt;p&gt;For instance, we use shadcn/ui and have a couple of graphs integrated already, but not all of them. A couple of months ago, I wanted to investigate how the data looked somewhere (to work on improving caches), just once. Llms are pretty good at making quick charts ‒ it doesn't want to use shadcn/ui and prefers using radix charts directly. But I don't have to maintain it, so who cares?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(There is a chance I'd need it again next time, and I still haven't learned, but that's a different problem)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don't want to go through a bunch of complaints and myths; the last two things I want to mention are tooling and errors. &lt;/p&gt;

&lt;p&gt;I don't have an exact venn diagram, but plenty of people who complained about Haskell tooling, for instance, are now using chat as an interface to their code. So... yeah... Make your own conclusions.&lt;/p&gt;

&lt;p&gt;But the situation with compilation errors is even more interesting. These errors ‒ in Haskell, PureScript, and so on ‒ are a huge pain point for many inexperienced and experienced developers. Talking about this has been in my backlog for a long time. Long story short, 90% of the time, if not more, the compilation errors are actually really good and precise. The problem is that they are often too precise. The compiler tells them exactly what the problem is, but in the words and concepts they don't understand. Because if they did, they wouldn't make the mistake in the first place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;firstLetter&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;firstLetter&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Couldn't match type ‘Char’ with ‘[Char]’
  Expected: [String]
    Actual: String
• In the first argument of ‘head’, namely ‘xs’
  In the expression: head xs
  In an equation for ‘firstLetter’: firstLetter xs = head xs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• No instance for ‘Num Bool’ arising from the literal ‘0’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not defending those errors, by the way. They still suck. For humans. But guess what, they are really good for the machines. Feed those suckers to llms. No need to be scared of compilation errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it works by virtue of being functional
&lt;/h3&gt;

&lt;p&gt;On this project, we used to be cautious with llm-generated code, but at some point, we ended up with a couple of modules that only Claudius reads and edits. Once, I was curious and wanted to check what we had there. There were 10 states for different in-flight statuses ‒ a common thing, when one action is happening, we don't want to allow others. So, each action/button had its own flag/state and checked all the others (9 checks) to determine if it should be disabled. It's terrible. &lt;/p&gt;

&lt;p&gt;So, if you look at one change or PR at a time, it's fine ‒ each one is just adding a normal state, nothing special. But if you take a step back and look at the bigger picture ‒ hell. It was a quick and easy fix to go from 10 states to 1. &lt;/p&gt;

&lt;p&gt;Refactoring and dealing with tech debt are quite important, but could be scary.&lt;/p&gt;

&lt;p&gt;This is a point for languages with fearless refactoring, like PureScript. I can't imagine how JavaScript developers, for instance, can survive this long term.&lt;/p&gt;

&lt;p&gt;But that is me, right now, on a specific project. This is not an argument for an FP future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who cares what programming language to use?
&lt;/h2&gt;

&lt;p&gt;I just want to know. Do you care what programming language to use? What are you doing about it?&lt;/p&gt;

&lt;p&gt;Do LLMs care what programming language to use? How does it affect things you care about? How will it affect?&lt;/p&gt;

&lt;p&gt;*This is February 2026; regardless of your opinion and experience, there is a chance, not a 0% chance, that programming languages will matter less because of the new abstraction level. But they might matter more. &lt;/p&gt;

&lt;p&gt;Could it be our last chance to choose and care about programming languages?&lt;/p&gt;

&lt;p&gt;I would love to ramble, speculate, and expand on this more, but probably some other time.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Also for that project, my side quest was to get people excited about PureScript, maybe teach a couple of people. This failed. Nobody really wanted to, and there is not much incentive at this point.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>haskell</category>
      <category>functional</category>
      <category>ai</category>
    </item>
    <item>
      <title>Functional takes on GoF design patterns</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Tue, 30 Dec 2025 04:17:48 +0000</pubDate>
      <link>https://forem.com/zelenya/functional-takes-on-gof-design-patterns-4jff</link>
      <guid>https://forem.com/zelenya/functional-takes-on-gof-design-patterns-4jff</guid>
      <description>&lt;p&gt;There is a meme that every (OOP) GoF design pattern can just be replaced with a function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr6f1f01mclzl0rjnl84.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmr6f1f01mclzl0rjnl84.PNG" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you think about it, it’s not that funny. Sure, there is some truth to that, and some patterns are already obsolete. But we also don’t just use functions in a vacuum — we write, compose, and manipulate them.&lt;/p&gt;

&lt;p&gt;Plus, jumping to those kinds of extremes is not helping anyone. We can build connections and grow on top of existing knowledge.&lt;/p&gt;

&lt;p&gt;So, let’s go through each of the 23 GoF patterns and see which one I actually see being used and what the functional alternatives are (if any). Most techniques and concepts will be language agnostic, with a few specific examples. We’ll see snippets in Haskell, Scala, PureScript, and Unison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creational Patterns
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Abstract Factory&lt;/li&gt;
&lt;li&gt;Builder&lt;/li&gt;
&lt;li&gt;Factory Method&lt;/li&gt;
&lt;li&gt;Prototype&lt;/li&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disclaimer: There are no OOP classes outside of OOP, so making instances of classes doesn’t make sense — but we still can talk and abstract over creating instances of things. Instead of classes, we'll be thinking in terms of modules, bundles of functionality, encapsulated APIs, or something along those lines...&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstract Factory
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Provide an interface for creating families of related or dependent objects without specifying their concrete classes.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I remember it as a &lt;strong&gt;toy factory&lt;/strong&gt; that, for example, can make bears, airplanes, and cars out of different materials (e.g., wood or plastic).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.data.common.dbproviderfactory?view=net-8.0&amp;amp;redirectedfrom=MSDN" rel="noopener noreferrer"&gt;In the oop world&lt;/a&gt;, we can use this to abstract over things like database connections and commands while generalizing over the database. So, we can write code that creates a database connection, executes some queries, and runs it with one database. Later, if we want to, we can swap the database by swapping the factory (and configuration).&lt;/p&gt;

&lt;p&gt;In FP, we don’t use abstract factories — we utilize functions and polymorphism (polymorphic types, and, in some cases, type classes). Let’s take a look at two Haskell libraries and how they address this.&lt;/p&gt;




&lt;p&gt;In &lt;a href="https://hackage.haskell.org/package/beam-postgres-0.5.4.1/docs/Database-Beam-Postgres.html#g:1" rel="noopener noreferrer"&gt;beam&lt;/a&gt;, we write abstract (backend/database-agnostic) code in terms of &lt;a href="https://hackage-content.haskell.org/package/beam-core-0.10.4.0/docs/Database-Beam.html#t:MonadBeam" rel="noopener noreferrer"&gt;&lt;code&gt;MonadBeam&lt;/code&gt;&lt;/a&gt; with polymorphic backend and generic functions (e.g, &lt;code&gt;select&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;query1&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;MonadBeam&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;query1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;allProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;all_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;warehouseDb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;runSelectReturningList&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt; &lt;span class="n"&gt;allProducts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Don't worry about the function signature for now. The important part is that it's abstract in terms of the database.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;We can then execute for a specific database using one of the backends; for example, &lt;a href="https://hackage.haskell.org/package/beam-postgres-0.5.4.1/docs/Database-Beam-Postgres.html#v:runBeamPostgres" rel="noopener noreferrer"&gt;&lt;code&gt;runBeamPostgres&lt;/code&gt;&lt;/a&gt; for &lt;a href="https://hackage.haskell.org/package/beam-postgres-0.5.4.1/docs/Database-Beam-Postgres.html#g:1" rel="noopener noreferrer"&gt;postgres&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;executeQuery&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Connection&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;executeQuery&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runBeamPostgres&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;query1&lt;/span&gt;
  &lt;span class="n"&gt;liftIO&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Query 1: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: We can also use the specific backend directly to access the full power of the database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/Zelenya/elephants/blob/main/src/Elephants/Beam.hs" rel="noopener noreferrer"&gt;See usage example&lt;/a&gt; and &lt;a href="https://haskell-beam.github.io/beam/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;In &lt;a href="https://hackage.haskell.org/package/persistent-2.14.6.2/docs/Database-Persist-SqlBackend-Internal.html#t:SqlBackend" rel="noopener noreferrer"&gt;persistent&lt;/a&gt;, it’s somewhat similar; we use functions that are abstract over the &lt;code&gt;backend&lt;/code&gt; type. (for sql databases, it’s &lt;a href="https://hackage.haskell.org/package/persistent-2.14.6.2/docs/Database-Persist-SqlBackend-Internal.html#t:SqlBackend" rel="noopener noreferrer"&gt;&lt;code&gt;SqlBackend&lt;/code&gt;&lt;/a&gt;). The library uses type classes (such as &lt;a href="https://hackage-content.haskell.org/package/persistent-2.17.1.0/docs/Database-Persist-Class.html#t:PersistStoreRead" rel="noopener noreferrer"&gt;&lt;code&gt;PersistStoreRead&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://hackage-content.haskell.org/package/persistent-2.17.1.0/docs/Database-Persist-Class.html#t:PersistStoreWrite" rel="noopener noreferrer"&gt;&lt;code&gt;PersistStoreWrite&lt;/code&gt;&lt;/a&gt;) to define database operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;insertStuff&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;MonadIO&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ReaderT&lt;/span&gt; &lt;span class="kt"&gt;SqlBackend&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;insertStuff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;newId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;insert&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="s"&gt;"Wood Screw Kit 1"&lt;/span&gt; &lt;span class="mi"&gt;245&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;liftIO&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Insert 1: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;newId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ReaderT SqlBackend m ()&lt;/code&gt; means we can access database configuration (e.g., database connection), can perform arbitrary IO operations, and don’t return anything meaningful (void).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And once again, we tie everything together with a specific backend, for example, using &lt;a href="https://hackage-content.haskell.org/package/persistent-sqlite-2.13.3.1/docs/Database-Persist-Sqlite.html#v:runSqlite" rel="noopener noreferrer"&gt;runSqlite&lt;/a&gt; or &lt;a href="https://hackage.haskell.org/package/persistent-postgresql-2.13.6.2/docs/Database-Persist-Postgresql.html" rel="noopener noreferrer"&gt;withPostgresqlPool&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Zelenya/elephants/blob/main/src/Elephants/PersistentEsqueleto.hs" rel="noopener noreferrer"&gt;See usage example&lt;/a&gt; and &lt;a href="https://www.yesodweb.com/book/persistent" rel="noopener noreferrer"&gt;docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Factory Method
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the simplest form, we want to hide the concrete implementation, so it can be created, returned, and used behind an abstraction/interface. A somewhat simple and common use case.&lt;/p&gt;

&lt;p&gt;Imagine we have some payment processing system and need to support multiple providers — for now, stripe and paypal.&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;PaymentProcessor&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;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalProcessor&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&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;class&lt;/span&gt; &lt;span class="nc"&gt;StripeProcessor&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&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;This is an example of tagless final — a popular approach to structuring code in Scala. We have an abstract interface &lt;code&gt;PaymentProcessor&lt;/code&gt; (some generic &lt;code&gt;F&lt;/code&gt;) and somewhat abstract implementations (&lt;code&gt;F&lt;/code&gt; with &lt;code&gt;Sync&lt;/code&gt;) that still don't commit to the final implementation, it could be IO, IO with explicit error handling, IO with tracing, etc.&lt;/p&gt;

&lt;p&gt;If we delegate the creation of the specific implementation to the &lt;code&gt;PaymentProcessorFactory&lt;/code&gt; — for example, based on the config — we get ourselves a simple factory.&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;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentProvider&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;object&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessorFactory&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;createProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentConfig&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;PaymentProcessor&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="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;paymentProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toLowerCase&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"paypal"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;PayPalProcessor&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;pure&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;case&lt;/span&gt; &lt;span class="s"&gt;"stripe"&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;StripeProcessor&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;pure&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;case&lt;/span&gt; &lt;span class="n"&gt;unknown&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unknown provider: $unknown"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;raiseError&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="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 we can always go a level deeper and abstract the abstractions:&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;PaymentProcessorFactory&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;createProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&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;PaymentProcessor&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="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DefaultPaymentProcessorFactory&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;config&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentConfig&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
  &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessorFactory&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="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;createProcessor&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;PaymentProcessor&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="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;paymentProvider&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toLowerCase&lt;/span&gt; &lt;span class="k"&gt;match&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;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExperimentBasedPaymentProcessorFactory&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessorFactory&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="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;class&lt;/span&gt; &lt;span class="nc"&gt;CountryBasedPaymentProcessorFactory&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessorFactory&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="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;&lt;em&gt;But let's not get wild here.&lt;/em&gt; Instead, let's look at a primitive usage example (note that there is nothing about specific implementations):&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;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentService&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;factory&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentProcessorFactory&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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;makePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&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;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;processor&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;createProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;    &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;result&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;refundPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&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;transactionId&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;PaymentResult&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;processor&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;createProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt;    &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;result&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;Factory methods are still used in different shapes and forms, especially in the scala world. As soon as you have a tagless final, mtl, service pattern, or whatever, factories sprout out naturally when we actually have multiple implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Singleton
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Ensure a class only has one instance, and provide a global point of access to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the presence of immutability and other things, singletons aren’t really needed. Most of the time, we create something once and then pass it around, knowing that nobody can modify it. For example, a db &lt;a href="https://github.com/Zelenya/elephants/blob/main/src/Elephants/Beam.hs#L117" rel="noopener noreferrer"&gt;connection&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Simple&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withConnect&lt;/span&gt; &lt;span class="n"&gt;connectionInfo&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;cleanUp&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;insertStuff&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;queryData&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;insertWithTransaction&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;queryWithJoins&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we need to modify something and access it concurrently, we use appropriate concurrency primitives; for example, &lt;a href="https://purerl.github.io/package-sets/Effect.Ref.html" rel="noopener noreferrer"&gt;Ref&lt;/a&gt; (aka &lt;a href="https://typelevel.org/cats-effect/docs/std/ref" rel="noopener noreferrer"&gt;Ref&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/base-4.16.3.0/docs/Data-IORef.html#t:IORef" rel="noopener noreferrer"&gt;IORef&lt;/a&gt;, …, you can find ref’s siblings all over).&lt;/p&gt;

&lt;p&gt;If we are in scala land and do need the simplest form of singleton (one instance of a class, not the double-thread-safe protected version, there are also &lt;a href="https://docs.scala-lang.org/tour/singleton-objects.html#:~:text=An%20object%20is%20a%20class,an%20object%20is%20a%20singleton." rel="noopener noreferrer"&gt;singleton objects&lt;/a&gt; modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Builder
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Separate the construction of a complex object from its representation so that the same construction process can create different representations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that we talk about scala, Builders are also quite common. It is one of the patterns that the community inherited and carried over from java.&lt;/p&gt;

&lt;p&gt;For example, here is &lt;a href="https://sttp.softwaremill.com/en/latest/requests/basics.html" rel="noopener noreferrer"&gt;a request definition using the sttp library&lt;/a&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;val&lt;/span&gt; &lt;span class="nv"&gt;request&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;basicRequest&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;cookie&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"login"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"me"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is a test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="s"&gt;"http://endpoint.com/secret"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s typical for fp libraries (and apis) to provide a basic/initial/default way to create data and build on top of.&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://x.com/unisonweb/status/1824161793549222243/photo/1" rel="noopener noreferrer"&gt;a unison example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see something similar in Haskell libraries and apis: &lt;code&gt;defaultRecord&lt;/code&gt; that can be updated via setters or via record update syntax. For example, to create &lt;a href="https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson.html#t:Options" rel="noopener noreferrer"&gt;Options&lt;/a&gt; for json codecs using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;defaultOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;omitNothingFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 Note: Sometimes it comes in the form of a default record and monoid instance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Wait. Is this Prototype, not Builder? Hm. Let’s revisit it in a second.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To conclude with builders, I’d say that they are somewhat common. Maybe not the way GoF envisioned, but whatever, builders are builders.&lt;/p&gt;

&lt;p&gt;Otherwise, in the fp world, we talk more about smart constructors and not builders. The focus is on making functions and APIs for creating only valid or validated values that can be safely passed around afterwards. For example, if we have a smart builder for an album, it should make sure that we can't create an album with an invalid year or an empty artist name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prototype
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s quite a functional pattern. &lt;em&gt;Even if I can’t draw a clear line between builders and prototypes&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;We saw this example of creating &lt;a href="https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson.html#t:Options" rel="noopener noreferrer"&gt;Options&lt;/a&gt; for json codecs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;defaultOptions&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;omitNothingFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is some record with defaults, we copy it, and update only what's needed.&lt;/p&gt;

&lt;p&gt;Copying data is bread and butter in FP. Some have it baked in. The above is the Haskell syntax for record updates. &lt;a href="https://docs.scala-lang.org/tour/case-classes.html#copying" rel="noopener noreferrer"&gt;Scala case classes have a copy method&lt;/a&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;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&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;amount&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Long&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;foo&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foo"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&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;bar&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Structural Patterns
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Adapter
&lt;/li&gt;
&lt;li&gt;Bridge
&lt;/li&gt;
&lt;li&gt;Composite
&lt;/li&gt;
&lt;li&gt;Decorator
&lt;/li&gt;
&lt;li&gt;Facade
&lt;/li&gt;
&lt;li&gt;Flyweight
&lt;/li&gt;
&lt;li&gt;Proxy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Structural design patterns are about organizing (structuring and re-structuring) objects and classes. And once again, a disclaimer. Because we don't have those outside of OOP, we’ll have to be more abstract and think in slightly different terms. I think we should focus on APIs and gluing code together. And to keep it interesting, we'll mix in various approaches.&lt;/p&gt;

&lt;p&gt;If you can recall, when we started with Abstract Factory, we already saw a couple of interesting-looking functions (function signatures):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;query :: (MonadBeam be m) =&amp;gt; m [Product]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;query :: (MonadIO m) =&amp;gt; ReaderT SqlBackend m ()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In Haskell, there is plain IO, mtl and transformers, custom monads (on top of those), IO + Reader(T), RIO, &lt;a href="https://github.com/fpco/unliftio" rel="noopener noreferrer"&gt;unliftio&lt;/a&gt;, services and &lt;a href="https://jaspervdj.be/posts/2018-03-08-handle-pattern.html" rel="noopener noreferrer"&gt;handle&lt;/a&gt; patterns, free monads, &lt;a href="https://hackage.haskell.org/package/freer-simple" rel="noopener noreferrer"&gt;freer-simple&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/extensible-effects" rel="noopener noreferrer"&gt;extensible-effects&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/fused-effects" rel="noopener noreferrer"&gt;fused-effects&lt;/a&gt;, &lt;a href="https://github.com/hasura/eff" rel="noopener noreferrer"&gt;eff&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/effectful" rel="noopener noreferrer"&gt;effectful&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/cleff" rel="noopener noreferrer"&gt;cleff&lt;/a&gt;, &lt;a href="https://github.com/polysemy-research/polysemy" rel="noopener noreferrer"&gt;polysemy&lt;/a&gt;, &lt;a href="https://github.com/tomjaguarpaw/bluefin" rel="noopener noreferrer"&gt;bluefin&lt;/a&gt;, and other effect libraries (&lt;em&gt;that I forgot to mention&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;“Remember this when someone says that it’s just functions in FP.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Adapter
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Convert the interface of a class into another interface that clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the simplest case, an &lt;em&gt;interface&lt;/em&gt; could imply the &lt;strong&gt;data&lt;/strong&gt; we move around. Imagine you have a module responsible for payments, you need to update to the latest stripe API (with breaking changes), but you don't want (or are not allowed) to change the sdk module. You can make an adapter.&lt;/p&gt;

&lt;p&gt;If you have a module with V1 data with a function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;getInvoices&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;InvoiceDataV1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can adapt it to V2 data like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;adaptInvoice&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;InvoiceDataV1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceDataV2&lt;/span&gt;

&lt;span class="c1"&gt;-- adapt from v1 to v2&lt;/span&gt;
&lt;span class="n"&gt;getInvoicesV2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;InvoiceDataV2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;getInvoicesV2&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt; 
  &lt;span class="n"&gt;v1Response&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;getInvoicesV1&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;
  &lt;span class="n"&gt;v2Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;adaptInvoice&lt;/span&gt; &lt;span class="n"&gt;v1Response&lt;/span&gt; 
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;v2Response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd say this is an adapter, alas, a boring one. A more interesting interpretation of &lt;em&gt;interfaces&lt;/em&gt; is the library and internal APIs ‒ APIs that we use to code with. It's a perfect opportunity to demonstrate what I meant in the introduction. &lt;/p&gt;

&lt;p&gt;There is no one way to write Haskell code. Even in the same code base, it's quite common to have a mix of approaches. For example, you just started a new service with a new fancy framework, and you need to integrate a library (internal or external) that uses something different. &lt;/p&gt;

&lt;p&gt;Let's start simple. You have a library that uses plain &lt;code&gt;IO&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;getInvoices&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you need to integrate it with your service that uses monad transformers, for example, &lt;code&gt;ResourceT&lt;/code&gt;. We need an adapter!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;getInvoicesLifted&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ResourceT&lt;/span&gt; &lt;span class="kt"&gt;Env&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;code&gt;ResourceT&lt;/code&gt; provides the ability to pass and read env. There are no global variables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can do the transformation manually (not going to show it), but you can also use a function just for this! In this case, &lt;a href="https://hackage.haskell.org/package/base-4.21.0.0/docs/Control-Monad-IO-Class.html#v:liftIO" rel="noopener noreferrer"&gt;&lt;code&gt;liftIO&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;getInvoicesLifted&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;InvoiceStatus&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ResourceT&lt;/span&gt; &lt;span class="kt"&gt;Env&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;getInvoicesLifted&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liftIO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getInvoices&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simplified. Depending on the context, complexity, and your team, this could be handled differently and kept more abstract. For instance, some people would prefer not to use an intermediate function like &lt;code&gt;getInvoicesLifted&lt;/code&gt; and use &lt;code&gt;liftIO&lt;/code&gt; at the call site. &lt;/p&gt;

&lt;p&gt;Some prefer to use alternative abstractions and utilities, such as &lt;a href="https://github.com/fpco/unliftio" rel="noopener noreferrer"&gt;&lt;code&gt;unliftio&lt;/code&gt;&lt;/a&gt;. But it all depends... Remember to check the documentation, recommendations, or your instincts for each particular case.&lt;/p&gt;

&lt;p&gt;For example, if you look at the docs of the &lt;a href="https://hackage-content.haskell.org/package/effectful-core-2.6.1.0/docs/Effectful.html#g:2" rel="noopener noreferrer"&gt;Effectufl&lt;/a&gt; library, you can see a whole section on integration with various cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bridge
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Decouple an abstraction from its implementation so that the two can vary independently&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think the idea is to use composition instead of inheritance to decouple the high-level interface that clients interact with from the concrete implementation details. The inheritance is not a problem outside of OOP, and you can decouple the public interface from the private in many different ways.&lt;/p&gt;

&lt;p&gt;For example, if we talk about libraries and apis, one common approach in Haskell and PureScript library design is using the &lt;code&gt;Internal&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;For example, let's look at the &lt;code&gt;bytestring&lt;/code&gt; library: the public API is &lt;a href="https://hackage-content.haskell.org/package/bytestring-0.12.2.0/docs/Data-ByteString.html" rel="noopener noreferrer"&gt;&lt;code&gt;Data.ByteString&lt;/code&gt;&lt;/a&gt;, but the lower-level API is in &lt;a href="https://hackage-content.haskell.org/package/bytestring-0.12.2.0/docs/Data-ByteString-Internal.html" rel="noopener noreferrer"&gt;&lt;code&gt;Data.ByteString.Internal&lt;/code&gt;&lt;/a&gt;. The Internal API is not stable and not meant for casual everyday usage; it's meant to provide flexibility for advanced users. For instance, see the disclaimer in the &lt;code&gt;containers&lt;/code&gt; &lt;a href="https://hackage-content.haskell.org/package/containers-0.8/docs/Data-IntMap-Internal.html" rel="noopener noreferrer"&gt;internals&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not everyone's favorite approach, and it doesn't solve all the problems, just one example.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Composite
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trees and recursions are native to FP. For instance, there are design patterns for traversing and recursing over nested data structures, called &lt;a href="https://research.utwente.nl/en/publications/functional-programming-with-bananas-lenses-envelopes-and-barbed-w/" rel="noopener noreferrer"&gt;recursion schemes&lt;/a&gt;. But I think it might be too specific to "represent" Composite; we can get away with something simpler. We can use &lt;strong&gt;type classes&lt;/strong&gt; to model Composite.&lt;/p&gt;

&lt;p&gt;Let's ignore the parts where we need to add and remove components, and focus on having a uniform interface for components and compositions of components. Imagine we need to have a Printable interface.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Don't think about oop classes, think about rust traits)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can implement a Printable instance for anything that needs to be printed. Let's rely on the default PureScript show for a number and return a string in quotes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we have an array of printable things, we can print them all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"["&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;intercalate&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we rely on a &lt;code&gt;Functor&lt;/code&gt; instance of &lt;code&gt;Array&lt;/code&gt;, a &lt;code&gt;map&lt;/code&gt; function. Another type class. Just imagine that we apply a function to every element of the list. &lt;/p&gt;

&lt;p&gt;To wrap up this example, let's look at printable json (with a mix of printable and not yet printable types):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;JSON&lt;/span&gt; 
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JNull&lt;/span&gt; 
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;JBool&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt; 
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;JNumber&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; 
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;JString&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; 
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;JArray&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;JObject&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Printable&lt;/span&gt; &lt;span class="kt"&gt;JSON&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="kt"&gt;JNull&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"null"&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JBool&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"true"&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JBool&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"false"&lt;/span&gt; 
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JNumber&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JString&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JArray&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;JObject&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;intercalate&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;printPair&lt;/span&gt; &lt;span class="n"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"}"&lt;/span&gt; 

&lt;span class="n"&gt;printPair&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There might be too many quotes, and I'm too lazy to test it. However, see how the json arrays and objects are handled. Composite!&lt;/p&gt;

&lt;h3&gt;
  
  
  Decorator
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My favorite use of decorator is to separate business logic from production-needed bells and whistles (things that help observability and performance, but can swallow the core logic if not tamed well).&lt;/p&gt;

&lt;p&gt;Let's revisit the &lt;em&gt;tagless-final&lt;/em&gt; processor that we used a while back.&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;PaymentProcessor&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;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalProcessor&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&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;class&lt;/span&gt; &lt;span class="nc"&gt;StripeProcessor&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="nc"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&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;If we want to add metrics without duplication and polluting the implementation, we can add a new implementation of the payment processor to enhance the functionality:&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;class&lt;/span&gt; &lt;span class="nc"&gt;MeteredProcessor&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="n"&gt;underlying&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Metrics&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
  &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
    &lt;span class="nv"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;measure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;underlying&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
    &lt;span class="nv"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;measure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;underlying&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Checks the cache first, before calling the api&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CachedProcessor&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="n"&gt;underlying&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
  &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessor&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="o"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&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;PaymentResult&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;def&lt;/span&gt; &lt;span class="nf"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&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;PaymentResult&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;And then decorate the original processors:&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;payPalProcessor&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MeteredProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PayPalProcessor&lt;/span&gt;&lt;span class="o"&gt;(...))&lt;/span&gt; &lt;span class="c1"&gt;// no cache&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;stripeProcessor&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MeteredProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CachedProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StripeProcessor&lt;/span&gt;&lt;span class="o"&gt;(...)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Facade
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don’t think it’s a real design pattern; it’s just good design (good manners). I don’t think it’s worth talking about here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flyweight
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Use sharing to support large numbers of fine-grained objects efficiently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one is also a normal phenomenon. In my naive and optimistic view, in the presence of immutability, we often get this for free.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Expense&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Expense&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; 
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;makeExpensiveValue&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Expense&lt;/span&gt; 
&lt;span class="n"&gt;makeExpensiveValue&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="n"&gt;trace&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Creating an expensive value: "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ExpensiveValue&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we create an instance of something expensive, it makes sense that it's created once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt; 
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeExpensiveValue&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="c1"&gt;-- Creating an expensive value: 3&lt;/span&gt;
&lt;span class="c1"&gt;-- Expense 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we want to create a whole list of those, it will still create one instance of &lt;code&gt;Expense 3&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;   
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;replicate&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;makeExpensiveValue&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;

&lt;span class="c1"&gt;-- Creating an expensive value: 3&lt;/span&gt;
&lt;span class="c1"&gt;-- Expense 15000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This still prints &lt;code&gt;Creating an expensive value&lt;/code&gt; once. The initialization happens once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide a surrogate or placeholder for another object to control access to it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think using Proxy is structurally similar to Decorator ‒ instead of providing an additional functionality, it restricts access, sometimes adds lazy initialization, and so on. Maybe the way the clients use it is different, doesn't make a huge difference. Let's just move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behavioral Patterns
&lt;/h2&gt;

&lt;p&gt;Finally, a set of patterns that have nothing to do with classes and objects, right?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chain of Responsibility
&lt;/li&gt;
&lt;li&gt;Command
&lt;/li&gt;
&lt;li&gt;Interpreter
&lt;/li&gt;
&lt;li&gt;Iterator
&lt;/li&gt;
&lt;li&gt;Mediator
&lt;/li&gt;
&lt;li&gt;Memento
&lt;/li&gt;
&lt;li&gt;Observer
&lt;/li&gt;
&lt;li&gt;State
&lt;/li&gt;
&lt;li&gt;Strategy
&lt;/li&gt;
&lt;li&gt;Template Method
&lt;/li&gt;
&lt;li&gt;Visitor&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Chain of Responsibility
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I think about chains and fallbacks, I think of Options:&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;first&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;stripePayments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;headOption&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;second&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;payPalPayments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;headOption&lt;/span&gt;

&lt;span class="nv"&gt;first&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;getOrElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We chain a few things until we get some payment. This isn't much of a chain of handlers, so let's look at something more interesting. Imagine we need to extract a &lt;em&gt;version&lt;/em&gt; out of the string, but we are dealing with questionable vendors (some return "v1.1", others "1.1.0", "2025-10-10", and so on):&lt;/p&gt;

&lt;p&gt;We can go through the list of parser functions until one of them returns some result, or we reach the end:&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;parseSemVer&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Version&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;parseCalVer&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Version&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;parseSoloVer&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Version&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;parseChained&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Version&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="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parseSemVer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parseCalVer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parseSoloVer&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;collectFirstSome&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;parseChained&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2025-10-10"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Some (CalVer ...)&lt;/span&gt;
&lt;span class="nf"&gt;parseChained&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"non-sense"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, we can use an explicit chain:&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;parseChained&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Version&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="n"&gt;str&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;parseSemVer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;parseCalVer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;parseSoloVer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&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 &lt;code&gt;&amp;lt;+&amp;gt;&lt;/code&gt; operator comes from the  &lt;code&gt;SemigroupK&lt;/code&gt; type class. Doesn't matter where it comes from. It's common. We won't go too deep into parser combinators, but this would be a fitting detour. They don't use Options (because we need meaningful errors), but do use plenty of typeclasses and operators to chain parsers together. If you are interested, consider exploring any Haskell library (such as &lt;a href="https://hackage.haskell.org/package/megaparsec-9.7.0/docs/Text-Megaparsec.html" rel="noopener noreferrer"&gt;megaparsec&lt;/a&gt;) or tutorial (e.g., &lt;a href="https://learn-haskell.blog/" rel="noopener noreferrer"&gt;Learn Haskell by building a blog generator&lt;/a&gt;). Note the use of the &lt;code&gt;&amp;lt;|&amp;gt;&lt;/code&gt; operator (it's related to the other one).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;parseTest&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;try&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="s"&gt;"let"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="s"&gt;"lexical"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"lexical"&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we return to our examples and want more than "just" parsing -- if we want arbitrary handlers of requests -- we can use &lt;code&gt;IO&lt;/code&gt; along with &lt;code&gt;Option&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;val&lt;/span&gt; &lt;span class="nv"&gt;fetchStripePayment&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;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Payment&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;fetchPayPalPayment&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;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Payment&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;createFallback&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;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Payment&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="nv"&gt;fetchStripePayment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;orElseF&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchPayPalPayment&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;orElseF&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createFallback&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is syntactic sugar. Those chains are more commonly seen as an &lt;code&gt;OptionT&lt;/code&gt; monad transformer:&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="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OptionT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchStripePayment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;OptionT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchPayPalPayment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;OptionT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createFallback&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The syntactic sugar in the previous snippet is to hide &lt;code&gt;OptionT&lt;/code&gt; from innocent eyes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And to nail the point. One of &lt;a href="https://http4s.org/v1/docs/service.html" rel="noopener noreferrer"&gt;the Scala HTTP libraries&lt;/a&gt; uses something similar to chain services (actual request handlers) together:&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;services&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweetService&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;helloWorldService&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Command
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is IO, or Task, or Effect, or whatever your language or library calls it — some data type to describe and pass around (effectful) computations. Let's use &lt;a href="https://pursuit.purescript.org/packages/purescript-effect/4.0.0/docs/Effect" rel="noopener noreferrer"&gt;Effect&lt;/a&gt; and PureScript for examples, and start simple.&lt;/p&gt;

&lt;p&gt;Let's start with a function that takes an arbitrary command and repeats it N times. We can log and differentiate the stages via the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;repeat&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;repeat&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="c1"&gt;-- todo: errors&lt;/span&gt;
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;"done"&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt; 
    &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"doing "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
    &lt;span class="n"&gt;repeat&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though we can pass any kind of action, I couldn't come up with anything better than passing another log &lt;code&gt;repeat 3 (log "- Action")&lt;/code&gt;. We can still see the repetition in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doing 3
- Action
doing 2
- Action
done
- Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we return to the payments domain and sketch out a more complex client, we can see the pattern more clearly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
 &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fetchPayments&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Payments&lt;/span&gt;
 &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prepareInvoice&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Payments&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;DateTime&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;  &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fetchPayments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prepareInvoice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;payments&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fetchPayments&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;dates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;yesterday&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tomorrow&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;invoices&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dates&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prepareInvoice&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;invoices&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, there is no exception handling or retries, but this could be the next logical step. This is not really Command, but it covers 80% use cases (if not more). We can pass different implementations of tasks/actions to the client, and the client decides in what order to execute those, how many times, and whatever else. &lt;/p&gt;

&lt;p&gt;This is a service pattern -- it's not very documented but not very restrictive. If you are coming from oop world, it's just an interface bundled together. And concrete implementations are also bundles of concrete functions. &lt;/p&gt;

&lt;p&gt;Anyway. If &lt;code&gt;IO&lt;/code&gt; and friends are not enough to express the Command, it could be integrated with the techniques used to replace the Interpreter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interpreter
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm pretty sure this is the most beloved design pattern among fp devs. For instance, EDSLs (embedded domain-specific languages) are very popular and one of the go-to examples for selling fp; the overlap between the patterns and the worlds is significant. &lt;/p&gt;

&lt;p&gt;We've already seen a few interpreters in the previous examples. But let's start with an alphabet: expressions.&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="c1"&gt;// operations&lt;/span&gt;
&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Expr&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Expr&lt;/span&gt; 
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Expr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// evaluators/interpreters&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Add&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&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="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;eval&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;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pprint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Expr&lt;/span&gt;&lt;span class="o"&gt;)&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;e&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Add&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&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="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"+"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;print&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which allows us to represent and interpret sentences like this one:&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;eval&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Lit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not a production-ready example; there are plenty of issues (it's hard to extend and add new operators, to support other types of literals, and so on), but this should be a good starting point. &lt;/p&gt;

&lt;p&gt;Now, let's hop a few learning steps ahead and look at real-world examples. When we are talking about free monads or tagless final, we are talking about interpreters. It's especially common in scala.&lt;/p&gt;

&lt;p&gt;One of the popular Scala libraries -- &lt;a href="https://typelevel.org/doobie/" rel="noopener noreferrer"&gt;doobie&lt;/a&gt; (for sql/persistence) uses &lt;a href="https://github.com/typelevel/doobie/tree/main/modules/postgres/src/main/scala/doobie/postgres/free" rel="noopener noreferrer"&gt;free monads&lt;/a&gt; and &lt;em&gt;"provides a functional way to construct programs (and higher-level libraries) that use JDBC"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://typelevel.org/doobie/docs/03-Connecting.html" rel="noopener noreferrer"&gt;For example&lt;/a&gt;, we can construct a program using a primitive sql statement that returns an int:&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;program&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;doobie.ConnectionIO&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="s"&gt;"select 42"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;query&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="py"&gt;unique&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it won't do anything unless we &lt;a href="https://typelevel.org/doobie/docs/03-Connecting.html#diving-deeper" rel="noopener noreferrer"&gt;run or interpret&lt;/a&gt; it:&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;xa&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Transactor&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Transactor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fromDriverManager&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;](???)&lt;/span&gt;

&lt;span class="n"&gt;program&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;transact&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xa&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// Interpret the doobie program into IO&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;unsafeRunSync&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Execute IO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, doobie provides an interpreter from its free monads to something more generic than IO, but ... I hope the point about interpreters is clear.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;While we're here, let's look at a visitor.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visitor
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's quite common to compare the Visitor pattern to pattern matching.&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="c1"&gt;// Visitor interface &lt;/span&gt;
&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;PaymentVisitor&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;visitPayPal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PayPalPayment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visitStripe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;StripePayment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; 
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visitBankTransfer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;BankTransferPayment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vs.&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;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;PayPalPayment&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;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;StripePayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;BankTransferPayment&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iban&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;And then you are supposed to laugh because a design pattern was invented to compensate for a lack of a language feature. But the thing is, life is not that simple. Not every functional language supports sum types and pattern matching. It's not a requirement for being functional. &lt;/p&gt;

&lt;p&gt;Those languages can get away with Church encoding / Böhm-Berarducci encoding (depending on whether they are typed or not).&lt;/p&gt;

&lt;p&gt;For example, instead of pattern matching on an optional value, it's enough to have a function that allows dealing with both cases when you have and do not have a value:&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="c1"&gt;// with pattern matching&lt;/span&gt;
&lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You have an int"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You have none"&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 scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// with Böhm-Berarducci encoding:&lt;/span&gt;
&lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;fold&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ifEmpty&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You have none"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// None case&lt;/span&gt;
  &lt;span class="o"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You have an int"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Some case&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, even though Scala has pattern matching, sometimes it can be more efficient to use a Visitor. See &lt;a href="https://github.com/typelevel/doobie/blob/main/modules/postgres/src/main/scala/doobie/postgres/free/largeobject.scala" rel="noopener noreferrer"&gt;doobie internals&lt;/a&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="c1"&gt;// Interface ... encoded via the visitor pattern.&lt;/span&gt;
&lt;span class="c1"&gt;// This approach is much more efficient than pattern-matching for large algebras.&lt;/span&gt;
&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Visitor&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="err"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, Java 21 comes with pattern matching. So, we'll see if it's time for Visitor to retire or not.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Speaking of folds&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Iterator
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Multiple things here. Depends on what kind of aggregation we're talking about.&lt;/p&gt;

&lt;p&gt;First, we have &lt;code&gt;Foldable&lt;/code&gt; and &lt;code&gt;Traversable&lt;/code&gt; type classes. Let's start with &lt;code&gt;Foldable&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="c1"&gt;-- 5&lt;/span&gt;
&lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="c1"&gt;-- True&lt;/span&gt;
&lt;span class="n"&gt;foldl&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="c1"&gt;-- -10&lt;/span&gt;
&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="c1"&gt;-- 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage isn't limited to just lists; we can &lt;a href="https://hoogle.haskell.org/?hoogle=Foldable&amp;amp;scope=set%3Astackage" rel="noopener noreferrer"&gt;find&lt;/a&gt; &lt;a href="https://hackage.haskell.org/package/base-4.21.0.0/docs/Prelude.html#t:Foldable" rel="noopener noreferrer"&gt;Foldable&lt;/a&gt; instances for all sorts of things; we can even derive those for free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; 
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Empty&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Leaf&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Foldable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Traversable&lt;/code&gt; extends &lt;code&gt;Foldable&lt;/code&gt; and abstracts away even more work for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="n"&gt;readMaybe&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- Just [1,2,3,4] &lt;/span&gt;

&lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;badStrings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
&lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="n"&gt;readMaybe&lt;/span&gt; &lt;span class="n"&gt;badStrings&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchUserData&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; 

&lt;span class="n"&gt;apiExample&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt; 
&lt;span class="n"&gt;apiExample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt; 
  &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;userIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; 
  &lt;span class="c1"&gt;-- Fetch all users (sequential) &lt;/span&gt;
  &lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="n"&gt;fetchUserData&lt;/span&gt; &lt;span class="n"&gt;userIds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those two play a vital role in iterating over things. But I wouldn't stop there, because we also have Optics. They allow us to deal with pretty much any sort of aggregation and complexity. A lot to cover here. But here is my favorite example.&lt;/p&gt;

&lt;p&gt;Imagine we have warehouses with stocks, and our task is to update all existing shoe stocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"inventory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"shoes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CHUCK TAYLOR ALL STAR LIFT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Converse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"brand"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Morrison"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"London"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Berlin"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something that we have to keep in mind: &lt;code&gt;inventory&lt;/code&gt; is optional, &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;stock&lt;/code&gt; are also optional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_warehouses&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Warehouse&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Warehouse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Warehouse&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_location&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_inventory&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Inventory&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Inventory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Inventory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_shoes&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Shoes&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Shoes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Shoes&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;ShoesName&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_brand&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Brand&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_stock&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Stock&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;-- We omit optic derivation/generation for simplicity (see else where)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start with composing optics to access what we need (existing stocks across warehouses and inventories):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;_allShoes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;warehouses&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;inventory&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;_Just&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;shoes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt;
&lt;span class="n"&gt;_existingStock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_allShoes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;_Just&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then we use it to update existing stocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="n"&gt;_existingStock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;warehouseResponse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, in this example, we are working with "underlying representation", but if we think of those snippets as library internals that expose only &lt;code&gt;_allShoes&lt;/code&gt; or &lt;code&gt;_existingStock&lt;/code&gt;, then we do provide a way to access the elements per pattern definition. &lt;/p&gt;

&lt;p&gt;And then if the internal representation changes (for instance, there are multiple inventories per warehouse, &lt;code&gt;inventory&lt;/code&gt; becomes &lt;code&gt;inventories&lt;/code&gt;), nothing changes from the user's perspective.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;_allShoes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;warehouses&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;inventories&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;shoes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt;
&lt;span class="n"&gt;_existingStock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_allShoes&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;_Just&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- No changes&lt;/span&gt;
&lt;span class="n"&gt;over&lt;/span&gt; &lt;span class="n"&gt;_existingStock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtract&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;warehouseResponse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mediator
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Define an object that encapsulates how a set of objects interacts. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similar to Facade; for me, not a real design pattern. We shouldn't write spaghetti code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memento
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the presence of immutability, the state can't be modified, so there is no encapsulation to violate. History can be a list of (previous) states. &lt;/p&gt;

&lt;p&gt;I used to work on a graph editor with PureScript, and we needed to keep a history of states to support undo. It was pretty much this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;EditorState&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;EditorState&lt;/span&gt; &lt;span class="c1"&gt;-- "Memento"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;undo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Editor&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Editor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, it was more complicated but more ergonomic. We also wanted to support undo and redo (go back and forth in history), so we used Zipper. I don't remember if we used &lt;a href="https://pursuit.purescript.org/packages/purescript-zipperarray/2.0.0/docs/Data.ZipperArray" rel="noopener noreferrer"&gt;a library&lt;/a&gt; or wrote something custom, but it provides an api like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ZipperArray&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ZipperArray&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;ZipperArray&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Observer
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This makes me think of functional reactive programming. I don't have much experience with it, so I'm unable to come up with an interesting illustration.&lt;/p&gt;

&lt;p&gt;But I do have experience with simpler functional streams, like fs2, that provide primitives like &lt;a href=""&gt;Topic&lt;/a&gt; and &lt;a href=""&gt;Signal&lt;/a&gt; to implement the publish-subscribe pattern, and other ways to define dependencies between objects:&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;Topic&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="py"&gt;flatMap&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;publisher&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fooStream&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;through&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;publish&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;subscriber&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;subscribe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;take&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="nv"&gt;subscriber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;concurrently&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;publisher&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 next thing that comes to mind is event handling with api like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;onEvent&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;

&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider web events, such as button clicks, form updates, and key presses. &lt;/p&gt;

&lt;p&gt;For example, this is an event handler from &lt;a href="https://pursuit.purescript.org/packages/purescript-react-basic/17.0.0" rel="noopener noreferrer"&gt;purescript-react-basic&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;EventFn&lt;/span&gt; &lt;span class="kt"&gt;SyntheticEvent&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventHandler&lt;/span&gt;

&lt;span class="c1"&gt;-- for simplicity, can be read as &lt;/span&gt;
&lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;SyntheticEvent&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SyntheticEvent&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventHandler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's &lt;a href="https://github.com/Zelenya/purescript-shadcn-tailwind-copypaste/blob/main/src/Components/LoginForm.purs#L66" rel="noopener noreferrer"&gt;use&lt;/a&gt; it to update the credentials when someone types into the password form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;input&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"P4$$W0RD"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="n"&gt;targetValue&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setPassword&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;And if you don't think that either fits as Observer, wait till you see what I have for the next one.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  State
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Probably, the closest kinda-functional kinda-backend kinda-version of this is (Finite) State Machines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────┐
│  Draft  │
└────┬────┘
     │ Send
     ▼
┌─────────┐
│  Sent   │──────┐
└────┬────┘      │
     │ Pay       │ Cancel
     ▼           ▼
┌─────────┐ ┌───────────┐
│  Paid   │ │ Cancelled │
└─────────┘ └───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Draft&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Sent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Paid&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cancelled&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;

&lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;  
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Pay&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cancel&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;case&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Draft&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
  &lt;span class="nf"&gt;case&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Sent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Pay&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;     &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
  &lt;span class="nf"&gt;case&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Sent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cancel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
  &lt;span class="nf"&gt;case&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Draft&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cancel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid state"&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;This is a very straightforward example, and there are many ways to implement a state machine, depending on the language, use case, and the rest of the code. There are libraries for this as well. For instance, there was a time when it was popular to use Akka FSM.&lt;/p&gt;




&lt;p&gt;Let's take a step back and think of the State more abstractly. There are no objects in fp, so if we are talking about altering an object's behavior, we should be talking about altering the behavior of functions. In theory, we can make the behavior dependent on input parameters. Different parameters -- different behavior. However, as we discussed in the context of Structural patterns, at some point, we have to start using higher-level concepts and ways to organize code.&lt;/p&gt;

&lt;p&gt;This is where the concept (or ability or whatever you want to call it) of State comes in. There are different implementations and approaches, but they all have the same interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Return the state (from internals of `m`)&lt;/span&gt;
&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;

&lt;span class="c1"&gt;-- Replace the state (inside the `m`)&lt;/span&gt;
&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is the &lt;a href="https://hackage.haskell.org/package/mtl-2.3.1/docs/Control-Monad-State-Lazy.html#t:State" rel="noopener noreferrer"&gt;State&lt;/a&gt; data type in the standard library. There are various States in each effect library (for example, &lt;a href="https://hackage-content.haskell.org/package/bluefin-0.2.0.0/docs/Bluefin-State.html" rel="noopener noreferrer"&gt;State&lt;/a&gt; in bluefin). Let's look at &lt;a href="https://hackage.haskell.org/package/mtl-2.3.1/docs/Control-Monad-State-Class.html" rel="noopener noreferrer"&gt;MonadState&lt;/a&gt; from the mtl library. I think it is the simplest one to use as an example, but the ideas apply to other libraries and implementations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;pay&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;MonadState&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;pay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;invoiceState&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;
  &lt;span class="c1"&gt;-- behavior depends on the internal state&lt;/span&gt;
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;invoiceState&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kt"&gt;Sent&lt;/span&gt; 
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="n"&gt;put&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoiceState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Paid&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;-- noop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have a &lt;code&gt;pay&lt;/code&gt; function that uses &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt; state functions. This function is quite abstract -- we say that we don't care who or how is going to call it, as long as they implement the &lt;code&gt;MonadState&lt;/code&gt; type class (&lt;code&gt;get&lt;/code&gt; and &lt;code&gt;put&lt;/code&gt;). They can store state in a single-threaded mutable variable, an atomic reference, or even on a disk; we don't care.&lt;/p&gt;

&lt;p&gt;And note that we can also chain those operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- modify is get + put in one operations&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;MonadState&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="kt"&gt;Sent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;MonadState&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="kt"&gt;Sent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Invoice&lt;/span&gt; &lt;span class="kt"&gt;Cancelled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;send&lt;/span&gt;
  &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;someCondition&lt;/span&gt; 
  &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="n"&gt;pay&lt;/span&gt;
  &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I also want to look at the State from the frontend perspective. We might be getting even more off track, but this State makes me think of &lt;a href="https://guide.elm-lang.org/architecture/" rel="noopener noreferrer"&gt;Elm architecture&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model&lt;/strong&gt; — the state of your application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt; — a way to turn your state into HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update&lt;/strong&gt; — a way to update your state based on messages&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you squint, it does alter its behavior when its internal state changes. And even though the basic description of the pattern doesn't mention how the state changes, here the state is changed via messages, which is very oop.&lt;/p&gt;

&lt;p&gt;You can see something similar in &lt;a href="https://hexdocs.pm/lustre/guide/02-state-management.html" rel="noopener noreferrer"&gt;lustre&lt;/a&gt;, a framework for building web apps in Gleam:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... the state of the application is stored in a single, immutable data structure called the model, and updated as messages are dispatched to the runtime.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've mostly used it via &lt;a href="https://pursuit.purescript.org/packages/purescript-react-basic-hooks/7.0.0/docs/React.Basic.Hooks.Aff#v:useAffReducer" rel="noopener noreferrer"&gt;useAffReducer&lt;/a&gt; hook &lt;a href="https://pursuit.purescript.org/packages/purescript-react-basic-hooks/7.0.0" rel="noopener noreferrer"&gt;purescript-react-basic-hooks&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;useAffReducer&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;AffReducer&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;Hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UseAffReducer&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;/\&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting part is at the end: &lt;code&gt;state + (action -&amp;gt; Effect Unit)&lt;/code&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide an initial state and a reducer function&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Strategy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, a design pattern that can be replaced by plain 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;val&lt;/span&gt; &lt;span class="nv"&gt;processPaymentStripe&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;processPaymentPayPal&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;p&gt;If we need to pass a payment processor, we can pass a function. That's it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Method
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Either I'm getting tired, or this could be similarly replaced by plain functions. We can pass "steps" via functions. And if we need something more complicated, we can use one of the many approaches we discussed before.&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;processPaymentStripe&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;processPaymentPayPal&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;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;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/qYEmJ8MYrs4"&gt;
  &lt;/iframe&gt;


.&lt;/p&gt;

</description>
      <category>functional</category>
      <category>scala</category>
      <category>oop</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Friction in programming and why FP isn’t mainstream</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Fri, 11 Jul 2025 15:10:58 +0000</pubDate>
      <link>https://forem.com/zelenya/friction-in-programming-and-why-fp-isnt-mainstream-4pc</link>
      <guid>https://forem.com/zelenya/friction-in-programming-and-why-fp-isnt-mainstream-4pc</guid>
      <description>&lt;p&gt;The other day, I was working on a dashboard: I wrote the core of it in purescript in a couple of hours, and then I got stuck fiddling with css for half an hour. I gave up. I switched to the BE, added all the endpoints, logic, and queries; then I got stuck for another half an hour fiddling with schema derivation (for the api docs). &lt;/p&gt;

&lt;p&gt;After that, I needed a break and finished the day. I had this bitter feeling — I’ve done a lot but haven’t finished the task, even though I was so close. I chewed on these annoying issues the rest of the day. I hate &lt;strong&gt;friction&lt;/strong&gt; in coding. With all the meetings and firefighting, it’s already a challenge to find time to code and get into the flow. I don’t want to be interrupted by stupid little things.&lt;/p&gt;

&lt;p&gt;Let’s talk about friction. &lt;/p&gt;

&lt;h2&gt;
  
  
  What does friction have to do with functional programming?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: Not saying that this is THE explanation for everything.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While I was chewing on this, I realized that functional programming is very guilty when it comes to friction. Regardless of the precise definition of FP, it’s intended to reinforce safer code and eliminate numerous bugs through types, abstractions, and functional design patterns. All of these come at a cost!&lt;/p&gt;

&lt;p&gt;It’s the same as when you want to secure your app — you add auth, mfa, vpn, and so on. All of these add friction but have a purpose. At the same time, not all security frictions are created equal — some are extremely tedious. You know that feeling when you have to go FROM ssh’ing to production TO layers of vpns and tools?&lt;/p&gt;

&lt;p&gt;Same with FP: some points of friction are intentional and others are not. &lt;/p&gt;

&lt;h2&gt;
  
  
  Types of friction
&lt;/h2&gt;

&lt;p&gt;While outside of FP, it’s acceptable to focus only on the happy path and overlook the rest, it’s unacceptable in FP. &lt;/p&gt;

&lt;p&gt;Imagine a function that fetches a role by user id (from postgres, for example). Somewhere in java land, you can say this function takes a &lt;strong&gt;user id&lt;/strong&gt; and returns &lt;strong&gt;a role&lt;/strong&gt;. Done. 1 input and 1 output. But it’s a lie. What about a database connection? It’s also an input. What if the user doesn’t exist or doesn’t have a role? There won’t be a role output.&lt;/p&gt;

&lt;p&gt;In functional land, you have to be explicit about &lt;strong&gt;all&lt;/strong&gt; the inputs (even a database connection), optional outputs, and even the fact that the function needs to access a database. All of this adds friction (for everyone who writes this function and uses it). But it also has a purpose. We want this. We don’t want bugs and errors at runtime. &lt;/p&gt;

&lt;p&gt;Let’s label this &lt;strong&gt;“intentional friction”&lt;/strong&gt;. It covers types (making them stronger and static), type classes, effects, and all the other things that make a programmer’s life better (but take time to master).&lt;/p&gt;

&lt;p&gt;By inverse, this leaves us with “&lt;strong&gt;unintentional friction&lt;/strong&gt;”. Vague error messages, flawed tooling, missing functionality or libraries, and everything that makes your blood boil.&lt;/p&gt;

&lt;p&gt;Regardless of whether you agree with those categories, the line between the two is blurry. Many things that are not-100-percent-intentionally introduce the friction that eventually smoothes away. It could be small things or other ways of doing “familiar” things. Let’s take “looking for the right function” as an example. It’s a simple thing. However, if you are new to a language ecosystem and don’t know how to utilize dot-completion or tools like hoogle, it can break your flow: you stop coding, switch to browser to search for a function, get distracted, switch to check your email or slack notifications, and then you have to invest substantial effort to get back into coding (flow).&lt;/p&gt;

&lt;h2&gt;
  
  
  Friction breaks flow
&lt;/h2&gt;

&lt;p&gt;I used to think that it’s just about steep learning curves or normal hurdles for beginners, but the problem is bigger — for me, it’s about all the things that can break the flow. And it sucks the most when various frictions interfere.&lt;/p&gt;

&lt;p&gt;Let’s take an average java developer trying to pick up a new language. I think rust and haskell offer similar learning curves: a bunch of unfamiliar concepts, new things to worry about, different syntax, whatever.&lt;/p&gt;

&lt;p&gt;But rust allows you to polish down the rough corners. For instance, unnecessary cloning, dynamic dispatch, and global state are generally discouraged; however, you can quickly use these and revisit your code later (in a second pass, for example). &lt;/p&gt;

&lt;p&gt;Haskell doesn’t let you cut corners — it’s either a haskell way (one of many haskell ways) or the highway…&lt;/p&gt;

&lt;p&gt;But it doesn’t mean that haskell is rigid or inflexible. Haskell is great for prototyping… When you know what you are doing. Because if you aren’t or return from a big break, it’s tough, not gonna lie. Even after all these years, when I return to haskell (or other fp language), I’m quite lost: how to glue the code? how to deal with errors? what to do about records? So many decisions and friction areas… I can hardly imagine how tough it must be for beginners. &lt;/p&gt;

&lt;p&gt;That’s one of the reasons why people don't want to try new languages and technologies — they keep using what they know, even if it's not good, because they are already used to that friction. It's less scary than the new unknown frictions. &lt;/p&gt;

&lt;p&gt;We talk about this a lot with one friend and occasionally wonder if it wasn’t a mistake for us to give up on spring. The framework isn’t perfect, but it eliminates most of the decision- and discovery-related friction, which is great.&lt;/p&gt;

&lt;p&gt;In either case, there are still plenty of other frictions left, so…&lt;/p&gt;

&lt;h2&gt;
  
  
  What can we do?
&lt;/h2&gt;

&lt;p&gt;Obviously, we all want someone to work on tooling, improve errors, write books, and reduce all sorts of friction. Usually, by “we”, we mean “someone else”. This won’t do! We should all take responsibility. I won’t ask you to contribute to open source or write books — I’ll ask you to start thinking and be more conscientious. &lt;/p&gt;

&lt;p&gt;We should be more diligent with decision-making; for example, choose the right level of abstractions and fitting techniques. We shouldn’t &lt;em&gt;always&lt;/em&gt; choose based on what we want to play with at the moment, but consider the longer-term consequences and the bigger picture. I can think of many examples from various communities of technical decisions that added unnecessary friction and had negative consequences for maintenance, adaptation, and the larger community. But those weren’t my decisions, and it’s not for me to criticize them right now.&lt;/p&gt;

&lt;p&gt;I have a good and common example, which I am occasionally guilty of: strength of types. &lt;/p&gt;

&lt;p&gt;Imagine we have an api that returns data for a role management dashboard. We need to add how many admins we have. How should we model it? It could be a string, an integer, an integer newtype, a refined type (for a natural number or something more precise — we might want to include or exclude 0). We can even bring it to the type level, so we can restrict some functions from compiling when the number is 0. What type is the best?&lt;/p&gt;

&lt;p&gt;It might be tempting to have the strongest guarantees. But consider the volume of friction it will add for using the api, extending it, and onboarding new developers. Is it worth it? &lt;/p&gt;

&lt;p&gt;Let’s say we chose the refinement type. What do we do if we start using a new storage library that doesn’t have the required instances for refinement types? What do we do if we need to add other numbers, for example, for super-admins and members? What if we want to ask a junior developer to update something small, and they have never heard of refinement types? Friction, friction, friction…&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;Coding in a state of flow is great, safe approachable code is great, and &lt;strong&gt;unintentional friction&lt;/strong&gt; sucks. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Friction&lt;/strong&gt; can be valuable. However, reducing &lt;strong&gt;unintentional&lt;/strong&gt; friction enhances the flow and increases the likelihood that people will do the right thing. This requires a lot of work and awareness, and is easier said than done. &lt;/p&gt;

&lt;p&gt;Looking at problems from a &lt;strong&gt;friction&lt;/strong&gt; point of view can be fruitful, but remember it’s not a hammer that fits all.&lt;/p&gt;

&lt;p&gt;With that being said, let’s extend the metaphor and look at two other things before wrapping up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why haskell is not more popular?
&lt;/h3&gt;

&lt;p&gt;A discussion about making haskell more popular arises multiple times a year. Every time with the same suggestions: better build tools, more learning resources and libraries, friendlier error messages and community, … and other things that reduce &lt;strong&gt;friction&lt;/strong&gt;!pie chart&lt;/p&gt;

&lt;p&gt;If you asked me what the haskell community should do to make haskell more popular, I could say focus on whichever of these reduces the most friction, and it would probably help. However, I believe the biggest friction is in people’s heads — haskell’s image. The perception of haskell magnifies its friction points.&lt;/p&gt;

&lt;p&gt;For instance, most languages have mediocre tooling full of friction. Tooling is hard. But somehow, haskell tooling is perceived to be one of the worst. So, someone tries haskell, struggles with the tooling, and instead of persevering (as they would with other things), they give up because that was their expectations from the start. The meme lives and spreads.&lt;/p&gt;

&lt;p&gt;So, unless haskell goes through a major rebranding, I don’t think it’s going to be popular. Bite-sized evolution isn’t enough.&lt;/p&gt;

&lt;p&gt;And should haskell be popular? A whole other question…&lt;/p&gt;

&lt;h3&gt;
  
  
  What about llms?
&lt;/h3&gt;

&lt;p&gt;On the contrary, I’m fascinated by how blunt llms deal with friction (so far). Changed some code and broke tests? Fuck it. Delete the tests. Need a slightly different function from what a library provides? Fuck it. Reinvent the wheel. &lt;/p&gt;

&lt;p&gt;Remove or ignore anything that’s in the way. Zero friction tolerance. &lt;/p&gt;

&lt;p&gt;One of the reasons some love llms and others hate them.&lt;/p&gt;

&lt;p&gt;It is what it is.&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/KS7bNieKvzE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>functional</category>
      <category>programming</category>
    </item>
    <item>
      <title>Programming: Between industry and craft</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Thu, 13 Mar 2025 03:48:00 +0000</pubDate>
      <link>https://forem.com/zelenya/programming-between-industry-and-craft-5go0</link>
      <guid>https://forem.com/zelenya/programming-between-industry-and-craft-5go0</guid>
      <description>&lt;h2&gt;
  
  
  Begin
&lt;/h2&gt;

&lt;p&gt;I grew up around people drawing, sewing, building, gardening, etc. I admired crafts and trades — it’s cool when people create and design things by hand. And not just by hand, they put skills into it, attitude, sometimes pride or love. In a way, they go beyond “just doing something” and tap into art territory. &lt;/p&gt;

&lt;p&gt;Years ago, when I stepped onto the IT path, I expected software engineers to be like craftsmen (like watchmakers or woodworkers, for instance). But recently, I realised I’m in the world of fast fashion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Between industry and craft
&lt;/h2&gt;

&lt;p&gt;I understand we’re a few industrial revolutions away from the &lt;em&gt;original crafts&lt;/em&gt;. We’re in a start-up world with a low germination rate. We MUST be fast or someone else will eat our part of the cake.&lt;/p&gt;

&lt;p&gt;I understand that modern watches and wooden furniture are rarely made by hand. Most apartments I’ve been to in Berlin looked like IKEA catalogues. &lt;/p&gt;

&lt;p&gt;But I’ve seen beautifully crafted furniture and watches. My question is: Where is beautifully crafted code? &lt;/p&gt;

&lt;p&gt;I’m guilty of this myself. Just look at the recent Gleam video: on multiple occasions, I leave shitty code and a promise to fix later. I wasn’t always like this. I used to be a better engineer just a couple of years ago. These days, I’m a “better engineer” but only for the business — I deliver faster and know what to focus on (as far as business is concerned). But why don’t I focus on the craft anymore? And it’s not just me — I notice this in others more and more.&lt;/p&gt;

&lt;p&gt;Some of it is industry’s fault, but some is our own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not built to last
&lt;/h3&gt;

&lt;p&gt;Memes about rewriting stuff to Rust are funny, but it’s not funny that we normalized rewrites for no major reason.&lt;/p&gt;

&lt;p&gt;A watchmaker can service a pocket watch from 1887, a woodworker can service a mid-century modern chair, both are likely to enjoy the process, and the results will last for years. There is admiration for well made older (vintage) stuff.&lt;/p&gt;

&lt;p&gt;And what do we do in our industry? We label code “legacy” the moment it leaves our local machine. What else do we do? We make “quick prototypes” that are never planned well but always end up in production… stay there for years… until we “rewrite it”. Of course, it rarely goes well and we never learn from our mistakes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🖼️ 1st system with cut-corners that’s hard to extend barely scales vs. bloated and over-engineered second-system&lt;/p&gt;

&lt;p&gt;There is hope: &lt;a href="https://softwareyoucan.love/" rel="noopener noreferrer"&gt;“Software you can love”&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Not picking the right tool for the job
&lt;/h3&gt;

&lt;p&gt;One might say: “But what if the language we picked for prototyping 5 years ago doesn’t scale any more?!” Is it? Is it the language’s fault? Maybe it’s a couple of small design decisions’ fault? Or your whole architecture’s? Or maybe, by Conway’s law, your entire organization is to blame?&lt;/p&gt;

&lt;p&gt;Sure, there are right tools for the job.&lt;/p&gt;

&lt;p&gt;For some jobs — for example, to cut some simple dowels — one can use a hand saw or a circular saw. It doesn’t matter much. &lt;/p&gt;

&lt;p&gt;For some jobs — for example, to make a short straight cut — a skilled worker can do a better job with a hand saw than a &lt;em&gt;junior&lt;/em&gt; with a jig saw.&lt;/p&gt;

&lt;p&gt;For some jobs — for example, to make a long straight cut — using a hand saw is a stupid (or an impossible idea).&lt;/p&gt;

&lt;p&gt;In other words, why are we wasting time brawling ****with go/java/haskell/whatever experts who pick their language of choice to do another web service? And when will we stop pretending there is no difference between writing a script to use once and maintainable code for years to come?&lt;/p&gt;

&lt;h3&gt;
  
  
  Not studying masters
&lt;/h3&gt;

&lt;p&gt;If history books are true, apprenticeship with a master was a common practice. These days, it’s more of a luxury or exception, so some artisans defer to master studies. For example, when you want to improve drawing and painting skills, you can study Michelangelo drawings, Stepan Kolesnikoff’s use of color, Dean Cornwell’s compositions, and so on.&lt;/p&gt;

&lt;p&gt;I don’t think bootcamps or seniors teaching juniors come anywhere close to that. The main goal of these is not to hone in software-engineering skills, it’s to get newbies to contribute good-enough code as soon as possible.&lt;/p&gt;

&lt;p&gt;Also, every time I onboarded someone or was onboarded by someone, the senior person had to do a walk of shame either around architecture decisions, developer experience, or code practices. I've never seen a code base someone was proud of.&lt;/p&gt;

&lt;p&gt;In good news, we have open source. It’s not easy to navigate and distinguish good from bad. But there are still some enthusiastic people who share good code and some are even happy to tutor others. Recently I’ve learned about &lt;a href="https://aosabook.org/en/" rel="noopener noreferrer"&gt;The Architecture of Open Source Applications&lt;/a&gt;, which is pretty good. So, overall, a pretty hopeful area. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Also, see &lt;a href="https://www.notion.so/9f2d7220257a435e8757978ae102cf58?pvs=21" rel="noopener noreferrer"&gt;Software Carpentry nonprofit&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Not mastering tools
&lt;/h3&gt;

&lt;p&gt;It takes time (sometimes a lifetime) to become great at anything. It’s an obvious fact to anyone who tried to learn and perfect something.&lt;/p&gt;

&lt;p&gt;I don’t care about overpaid and over-self-confident juniors and middles. What worries me is that we promote the best, most valuable engineers out of their craft. Instead of using their hard-learned skills, they waste time sitting in meetings, writing documents nobody reads, or running after people trying to persuade other already-overloaded teams to do more things and improvements.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;illusion of free choice: manager path and principal path&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  FP part
&lt;/h2&gt;

&lt;p&gt;At this point, I was going to bring it back to functional programming, but whatever I wanted to say I already did in the video on values (&lt;a href="https://dev.to/zelenya/do-your-values-align-with-fp-values-48l9"&gt;Do your Values align with FP Values?&lt;/a&gt;) and on labels (&lt;a href="https://dev.to/zelenya/on-superiority-of-functional-programming-and-other-labels-36dk"&gt;On “superiority” of (functional) programming and other labels&lt;/a&gt;). So, let’s wrap it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;You can say that it’s a bit unfair, because our industry is still young and immature, while people have been building furniture for thousands of years and watches for centuries… &lt;/p&gt;

&lt;p&gt;But. We’re in the LLM age now. Regardless of what you think of llms, and if you think that they're going to replace all, some, or none of the jobs, they are here and they are part of the industry. So, how much more “new” code and values can we even contribute? In this month, year, or maybe two? Will we fly high into the craft of engineering or dive deeper into the fast-fashion industry? &lt;/p&gt;




&lt;p&gt;If all of this sounds unfamiliar, you’re in the minority. If you are a part of the community or a company of craft-engineers, please share. I’ve heard of &lt;a href="https://softwareyoucan.love/" rel="noopener noreferrer"&gt;https://softwareyoucan.love/&lt;/a&gt; and a few other exciting things. But would love to learn about more. This question is not for youtube engagement or anything like that, you can DM me anywhere else.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>PureScript for Scala developers</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Sat, 30 Nov 2024 04:29:38 +0000</pubDate>
      <link>https://forem.com/zelenya/purescript-for-scala-developers-2o75</link>
      <guid>https://forem.com/zelenya/purescript-for-scala-developers-2o75</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is mostly based on &lt;a href="https://dev.to/zelenya/haskell-for-scala-developers-2fg3"&gt;Haskell for Scala developers&lt;/a&gt;. If you’ve seen that one already, your most interesting sections are Row Polymorphism, Aff and Effect, and Tooling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once again, we’ll cover the main differences, similarities, major gotchas, and most useful resources. Consider this a rough map.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic syntax and attitude
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Driving on the wrong side of the road
&lt;/h3&gt;

&lt;p&gt;You have to get used to reading chains of operations “in the opposite direction”. Take this Scala code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extractErrorMessage&lt;/span&gt;&lt;span class="nb"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asLeft&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are multiple ways to translate it to PureScript; the most straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the order of &lt;strong&gt;functions&lt;/strong&gt; and how we call &lt;strong&gt;functions&lt;/strong&gt; (e.g., no parentheses after &lt;code&gt;message&lt;/code&gt;). We can avoid even more parentheses by using the function application operator (&lt;code&gt;f $ x&lt;/code&gt; is the same as &lt;code&gt;f x&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can avoid the rest of the plumbing by using function composition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good news: You can reverse all of it and read from left to right if you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from left to right to right&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from left to right to right&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad news: more syntax to get used to. In the wild, you will see all of these styles and their mix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function signatures
&lt;/h3&gt;

&lt;p&gt;Did you notice that functions had no type signatures?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 PureScript is pretty good at inferring types. But some error messages aren’t newcomer-friendly; the more explicit types you add — the better the error messages.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the explicit universal quantifier, &lt;code&gt;forall&lt;/code&gt; (we’ll talk about this later).&lt;/p&gt;

&lt;p&gt;The type signature goes above the function definition. It might feel awkward to connect a name to a type, but on the other hand, it allows you to focus on types (while ignoring the names).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bar&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Credentials&lt;/span&gt;
&lt;span class="n"&gt;bar&lt;/span&gt; &lt;span class="n"&gt;user&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;unsafeCrashWith&lt;/span&gt; &lt;span class="s"&gt;"Not implemented"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 The &lt;code&gt;unsafeCrashWith&lt;/code&gt; function is a cousin of &lt;code&gt;???&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Common error. Could not match type
&lt;/h3&gt;

&lt;p&gt;Because in PureScript, we use parentheses differently from the way we do in Scala, the most common newcomer error is forgetting or misusing them. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;good = bar user (Just password)

oops = bar user Just password
                ^^^^

  Could not match type
    Function t0
  with type
    Maybe
  while trying to match type t0 -&amp;gt; Maybe t0
    with type Maybe Password
  while checking that expression Just
    has type Maybe Password
  in value declaration x
  where t0 is an unknown type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, the compilation error is good: the &lt;code&gt;foo&lt;/code&gt; takes a value with type &lt;code&gt;Maybe Password&lt;/code&gt;, but we passed &lt;code&gt;Just&lt;/code&gt; (which is a constructor, aka a function that takes a value of any type and returns &lt;code&gt;Maybe&lt;/code&gt; of that type). However, in practice, it’s not that good — the actual error is that the programmer forgot parentheses and now passes &lt;code&gt;Just&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; separately (three arguments instead of two). &lt;/p&gt;

&lt;h3&gt;
  
  
  Names don’t matter?
&lt;/h3&gt;

&lt;p&gt;Another slightly different but related thing is about common function names and operators.&lt;/p&gt;

&lt;p&gt;There is &lt;a href="https://pursuit.purescript.org/search?q=map" rel="noopener noreferrer"&gt;map&lt;/a&gt;, but it’s more common to use operators: &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;#&amp;gt;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="err"&gt;∷&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="err"&gt;∷&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;#&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s no &lt;code&gt;flatMap&lt;/code&gt;, there &lt;a href="https://pursuit.purescript.org/packages/purescript-prelude/6.0.1/docs/Control.Bind#v:bind" rel="noopener noreferrer"&gt;&lt;code&gt;bind&lt;/code&gt;&lt;/a&gt; and  &lt;a href="https://pursuit.purescript.org/packages/purescript-prelude/6.0.1/docs/Control.Bind#v:(%3E%3E=)" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;&lt;/a&gt; (bind operator), and in general PureScript codebases (and developers) are more tolerable towards operators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
  &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;
  &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;traverse&lt;/code&gt; is still &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:traverse" rel="noopener noreferrer"&gt;&lt;code&gt;traverse&lt;/code&gt;&lt;/a&gt;, and everything else you can pick up as you go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indentation
&lt;/h3&gt;

&lt;p&gt;Unless you embraced Scala 3 and brace-less syntax, after years of curly brackets, it’s going to be hard to adjust to the indentation-based syntax, and it’s going to feel unnatural.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="err"&gt;∷&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;JSX&lt;/span&gt;
&lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;
  &lt;span class="n"&gt;userInfo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;renderUser&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;
    &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;showError&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt;
  &lt;span class="kr"&gt;let&lt;/span&gt;
    &lt;span class="n"&gt;hasActive&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;subscriptionInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hasActive&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="n"&gt;renderSubscriptions&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt;
      &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;renderBox&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;userInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionInfo&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⌛ &lt;code&gt;Effect&lt;/code&gt; is like &lt;code&gt;IO&lt;/code&gt;, we’ll cover it later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The minimal thing I can recommend here is to use a formatter, split things into smaller chunks, and when you are not sure, just push things left and right 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic concepts and fp
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Function composition and Currying
&lt;/h3&gt;

&lt;p&gt;In PureScript (like in &lt;a href="https://youtu.be/K76vrOzU53o" rel="noopener noreferrer"&gt;Haskell&lt;/a&gt;), function composition and currying are first-class citizens. Both are powerful enough to make the code tidier and more elegant, as well as the opposite. You certainly have to practice to get better at writing and reading.&lt;/p&gt;

&lt;p&gt;If you find some code confusing (or you wrote some code that the compiler doesn’t accept), try rewriting it: make it more verbose, introduce intermediate variables, add explicit types, and so on. It’s ok. It’s not a one-liner competition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;

  &lt;span class="n"&gt;userSubscription&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Subscription&lt;/span&gt;
  &lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;code&gt;where&lt;/code&gt; declarations are a convenient way to scope things within a function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, if it feels like the number of arguments is getting out of control (or you miss having values and types right next to each other), try introducing records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userInfo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;BundleServiceUrl&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cache&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;UserInfo&lt;/span&gt;
&lt;span class="n"&gt;userInfo&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unsafeCrashWith&lt;/span&gt; &lt;span class="s"&gt;"Not implemented"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;BundleServiceUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Cache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;RequestIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;userInfo2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;RequestIds&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
&lt;span class="n"&gt;userInfo2&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unsafeCrashWith&lt;/span&gt; &lt;span class="s"&gt;"Not implemented"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note how we pattern match in the case of &lt;code&gt;RequestIds&lt;/code&gt;, we’ll touch on records later.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Purity
&lt;/h3&gt;

&lt;p&gt;When writing PureScript, you cannot just use a quick &lt;code&gt;var&lt;/code&gt; or a temporary &lt;code&gt;println&lt;/code&gt;. Depending on your experience and workflows, it can be or not be a big deal. &lt;/p&gt;

&lt;p&gt;You can start by getting familiar with &lt;a href="https://pursuit.purescript.org/packages/purescript-debug/6.0.2/docs/Debug#v:spy" rel="noopener noreferrer"&gt;Debug (spy)&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spy&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 See &lt;a href="https://studio.youtube.com/video/iAzaShuVpPc/edit" rel="noopener noreferrer"&gt;Debugging without a “real” debugger&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Modules, Imports, and Exports
&lt;/h3&gt;

&lt;p&gt;There are no classes and objects. &lt;/p&gt;

&lt;p&gt;You might quickly run into a problem with naming conflicts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.String&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.List&lt;/span&gt; 

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;
&lt;span class="c1"&gt;--    ^^^^^^&lt;/span&gt;
&lt;span class="c1"&gt;-- Conflicting definitions are in scope for value length from the following modules:&lt;/span&gt;
&lt;span class="c1"&gt;--   Data.List&lt;/span&gt;
&lt;span class="c1"&gt;--   Data.String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to get into a habit of using qualified imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.String&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="c1"&gt;-- stylistic choice&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.List&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;S&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some libraries suggest the users to qualify their imports; some people prefer to qualify &lt;strong&gt;all&lt;/strong&gt; their imports, but, at the end of the day, it’s a personal/team choice. Start using qualified imports for collections (containers) and strings, and see how it goes.&lt;/p&gt;




&lt;p&gt;There are no access modifiers (no &lt;code&gt;private&lt;/code&gt; or &lt;code&gt;public&lt;/code&gt; keywords). You can either export everything from the module (in the module declaration on the top):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Test&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or export (aka make public) only specific functions, data types, type classes, etc.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Test&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nf"&gt;publicMethod&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;PublicConstructor&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Example&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Product Types
&lt;/h3&gt;

&lt;p&gt;PureScript records correspond to JavaScript objects. Here is a function that takes some user model and bumps their score:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bumpCounter&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&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="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;-- { counter: 11, userId: "test" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can make it tidier by introducing a type alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt;
&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&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="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also use various combinators to work with &lt;a href="https://pursuit.purescript.org/packages/purescript-record/4.0.0/docs/Record" rel="noopener noreferrer"&gt;records&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt;
&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Proxy&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"counter"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the code is a bit longer, but imagine chaining and using multiple operations like unions, deleting and renaming fields, etc. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🍪 There is an upcoming alternative syntax for this — using  &lt;code&gt;@&lt;/code&gt; (Visible type applications) instead of &lt;code&gt;Proxy …&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sum types
&lt;/h3&gt;

&lt;p&gt;Sum types (aka Tagged Unions) shouldn't be too surprising. Those are declared via &lt;code&gt;data&lt;/code&gt; and can be deconstructed through pattern matching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Member&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Admin&lt;/span&gt;

&lt;span class="n"&gt;hasRights&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;
&lt;span class="n"&gt;hasRights&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
  &lt;span class="kt"&gt;Member&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="s"&gt;"special"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
  &lt;span class="kt"&gt;Admin&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;
  &lt;span class="kt"&gt;Member&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Newtypes
&lt;/h3&gt;

&lt;p&gt;Newtypes are introduced with the &lt;code&gt;newtype&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Row Types
&lt;/h3&gt;

&lt;p&gt;It’s one of the coolest PS features but also one of the main sources of confusion and errors for newcomers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UserScore&lt;/code&gt; is a record and we can make a value of the type &lt;code&gt;UserScore&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt;
&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has two fields: userId of type &lt;code&gt;String&lt;/code&gt; and counter of type &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, those are rows (note the parentheses):&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;ClosedRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;Int&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;OpenRow&lt;/span&gt; &lt;span class="kt"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;Int&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s not worry about the difference right now. A row of types represents an unordered collection of named types. Rows are not of kind &lt;code&gt;Type&lt;/code&gt;. Rows cannot exist as a value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🌯 Kinds are types of types. It’s what distinguishes &lt;code&gt;List&lt;/code&gt; from &lt;code&gt;List[Int]&lt;/code&gt; (among other things). You can’t create a value of just &lt;code&gt;List&lt;/code&gt; of just &lt;code&gt;Option&lt;/code&gt;, but you can create values of &lt;code&gt;List[Int]&lt;/code&gt;, &lt;code&gt;Option[String]&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/purescript/documentation/blob/master/language/Types.md#rows" rel="noopener noreferrer"&gt;Row types&lt;/a&gt; unlock many typelevel operations. We won’t go into details here.&lt;/p&gt;

&lt;p&gt;The simplest application of rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;DateTime&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;UserScore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;enrichUser&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;UserResponse&lt;/span&gt;
&lt;span class="n"&gt;enrichUser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unsafeCrashWith&lt;/span&gt; &lt;span class="s"&gt;"???"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common error. Could not match kind Type with kind Row Type
&lt;/h3&gt;

&lt;p&gt;We can add rows to get a row, pass row types, return them, whatever. Because it’s new for many, there is this one typelevel error that needs attention:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not match kind

  Type

with kind

  Row Type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It means, you passed a type (usually, representing a record) where the row type was expected. &lt;/p&gt;

&lt;p&gt;For example, there is this type alias for declaring &lt;a href="https://github.com/rowtype-yoga/purescript-react-basic-dom-beta/blob/v0.1.1/src/Beta/DOM/Internal.purs#L78" rel="noopener noreferrer"&gt;components&lt;/a&gt; that that takes a row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;FFIComponent&lt;/span&gt; &lt;span class="n"&gt;props&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 pass it props we care about as a row type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;ButtonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;asChild&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;buttonExample&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;FFIComponent&lt;/span&gt; &lt;span class="kt"&gt;ButtonProps&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if we pass a record by accident, we get that error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;ButtonPropsOops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;asChild&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;buttonExample&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;FFIComponent&lt;/span&gt; &lt;span class="kt"&gt;ButtonPropsOops&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not match kind

  Type

with kind

  Row Type
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🌯 Records and rows are related but different concepts. Once again remind yourself about kinds. If you’ve conquered &lt;code&gt;F[_]&lt;/code&gt;, you can conquer &lt;strong&gt;row types&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Polymorphism&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What in the Java world is called generics, in the PureScript world is called parametric polymorphism.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- a is a type parameter&lt;/span&gt;
&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PS, polymorphic functions require an explicit &lt;code&gt;forall&lt;/code&gt; (to declare type variables before using them). Other than that, in general practice, it’s not that different.&lt;/p&gt;

&lt;h3&gt;
  
  
  Row Polymorphism
&lt;/h3&gt;

&lt;p&gt;We can rewrite the &lt;code&gt;bumpCounter&lt;/code&gt; function to make it more polymorphic (more generic):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;bumpCounter&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;bumpCounter&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&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="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For simplicity, the &lt;code&gt;userId&lt;/code&gt; isn't used in the function body.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;r&lt;/code&gt; is a row of types (zero or more of some other rows that we don't care about). In other words, the function takes (and returns) any record that has a field &lt;code&gt;userId&lt;/code&gt; with type &lt;code&gt;String&lt;/code&gt;, a &lt;code&gt;counter&lt;/code&gt; with type &lt;code&gt;Int&lt;/code&gt;, and whatever else.&lt;/p&gt;

&lt;p&gt;To make it more interesting, we can change the type of the counter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;processCounter&lt;/span&gt;
  &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
   &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&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="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;processCounter&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In either case, we can pass any record that fits the shape, including existing &lt;code&gt;UserScore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;processCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;-- { counter: "11", userId: "y" }&lt;/span&gt;

&lt;span class="n"&gt;processCounter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;whatever&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;-- { counter: "11", payments: [1,2,3], userId: "y", whatever: 2 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type classes
&lt;/h3&gt;

&lt;p&gt;Unlike Scala, PureScript has built-in type classes — there's (guaranteed to be) at most one instance of a type class per type. &lt;/p&gt;

&lt;p&gt;Good news: &lt;strong&gt;No need to worry about imports!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are other things you’ll have to worry about at some point, but don’t worry about them right now. You can start by declaring the type class instances next to the type class (in the same module) or next to the data. &lt;/p&gt;

&lt;p&gt;Sometimes, when you need a new (custom) instance, you can introduce a newtype:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- User is declared in some other module&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; 

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Arbitrary&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;arbitrary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arbitrary&lt;/span&gt;
    &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arbitrary&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And remember that you can get a lot for free with deriving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deriving
&lt;/h3&gt;

&lt;p&gt;In PureScript, you can derive quite a lot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Newtype&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;
&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Eq&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt;
&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt;
&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;ReadForeign&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt;
&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;WriteForeign&lt;/span&gt; &lt;span class="kt"&gt;JwtAccessToken&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Meta Programming
&lt;/h2&gt;

&lt;p&gt;The most common way to generate boilerplate in PureScript is &lt;strong&gt;generic programming&lt;/strong&gt;. Not java generics. Even more generic generics!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 That’s one of the reasons not to refer to parametric polymorphism as just (java) generic types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Generic programming&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Generic programming comes in different shapes and forms. PureScript has a built-in &lt;a href="https://pursuit.purescript.org/packages/purescript-prelude/6.0.1/docs/Data.Generic.Rep#t:Generic" rel="noopener noreferrer"&gt;&lt;code&gt;Generic&lt;/code&gt;&lt;/a&gt; class is the &lt;a href="https://github.com/purescript/purescript-prelude" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-prelude&lt;/code&gt;&lt;/a&gt; library. The most common usage is deriving show instance for sum types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Generic.Rep&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Show.Generic&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;genericShow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Member&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Admin&lt;/span&gt;

&lt;span class="n"&gt;derive&lt;/span&gt; &lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Generic&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genericShow&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;🌯 Generics are kinda like shapeless.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Best practices (and concepts)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Abstractions and type classes
&lt;/h3&gt;

&lt;p&gt;It’s important to know your type classes. Those are a must: &lt;code&gt;Functor&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt;, &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;Semigroup&lt;/code&gt;, &lt;code&gt;Monoid&lt;/code&gt;, &lt;code&gt;Foldable&lt;/code&gt;, &lt;code&gt;Traversable&lt;/code&gt;, and &lt;code&gt;Alternative&lt;/code&gt;. If the library has a functionality that can be provided by one of those (&lt;em&gt;e.g., smooshing or mapping things&lt;/em&gt;), it’s likely that it’s going to be provided and won’t be very documented.&lt;/p&gt;

&lt;p&gt;Addition and multiplication come via &lt;code&gt;Semiring&lt;/code&gt;s; boolean operation come via &lt;code&gt;HeytingAlgebra&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aff and Effect
&lt;/h3&gt;

&lt;p&gt;Instead of one &lt;code&gt;IO&lt;/code&gt; data type, there are two, &lt;code&gt;Aff&lt;/code&gt; and &lt;code&gt;Effect&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Both can be used with the do notation (&lt;em&gt;for comprehension&lt;/em&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Aff&lt;/code&gt; is for &lt;strong&gt;async&lt;/strong&gt;hronous computations, &lt;code&gt;Effect&lt;/code&gt; is for synchronous, and they can’t be mixed. If you know of function coloring, you should know why; and if not — let’s look at examples.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 A reminder: JavaScript is single-threaded and achieves concurrency via asynchronous operations and event loop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, for example, api call has to be &lt;strong&gt;async&lt;/strong&gt;hronous. We don’t want to block everything waiting for response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Aff&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;apiUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;-- returns Aff Response&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiUrl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"/users/"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;GET&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="c1"&gt;-- fromJSON :: forall json. ReadForeign json =&amp;gt; Aff Foreign -&amp;gt; Aff json&lt;/span&gt;
    &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fromJSON&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="c1"&gt;-- throwError :: forall e m a. MonadThrow e m =&amp;gt; e -&amp;gt; m a&lt;/span&gt;
    &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;throwError&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="s"&gt;"Unexpected response status: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Button click, on the other hand, should respond (have an effect) right away:&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="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="nc"&gt;SyntheticEvent&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Effect&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can’t mix the two, but we can convert one to another. It’s easy to make a synchronous computation (&lt;code&gt;Effect&lt;/code&gt;) &lt;strong&gt;asyn&lt;/strong&gt;chronous (&lt;code&gt;Aff&lt;/code&gt;). For example, we can use &lt;code&gt;liftEffect&lt;/code&gt; to add something to our &lt;strong&gt;async&lt;/strong&gt; call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- This is for illustration purposess only&lt;/span&gt;
&lt;span class="n"&gt;syncLog&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;syncLog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;

&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Aff&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;apiUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fetch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apiUrl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"/users/"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;GET&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;-- This is where we transform Effect to Aff&lt;/span&gt;
  &lt;span class="n"&gt;liftEffect&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;syncLog&lt;/span&gt; &lt;span class="s"&gt;"This is sync"&lt;/span&gt;
  &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fromJSON&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
    &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;throwError&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="s"&gt;"Unexpected response status: "&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And what if we want to make an api call on a button click? Make an &lt;strong&gt;async&lt;/strong&gt;hronous computation (Aff) synchronous (Effect)? The easiest thing to do is to fork the computation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;setUserProfile&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Aff&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;setUserProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;try&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="c1"&gt;-- Aff&lt;/span&gt;
  &lt;span class="n"&gt;liftEffect&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setUserProfile&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="c1"&gt;-- Effect&lt;/span&gt;
    &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;showError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;     &lt;span class="c1"&gt;-- Effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;button&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ghost"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"md"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="n"&gt;preventDefault&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;launchAff_&lt;/span&gt; &lt;span class="n"&gt;setUserProfile&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;"Clicked"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On click, it’s going to &lt;strong&gt;asyn&lt;/strong&gt;chronously make an api call (which then depending on result either sets some user info or shows an error) but also (concurrently) log a message to the console. No blocking. &lt;/p&gt;

&lt;p&gt;Note that we throw away the fiber handle. This isn't always desirable. In this case, we don’t care about the result, only side effects, so it's ok.&lt;/p&gt;

&lt;p&gt;The other option is to use something like the &lt;code&gt;useAff&lt;/code&gt; hook or &lt;code&gt;useAffReducer&lt;/code&gt; to deal with async stuff. For example, button sync updates some state/model, and then that triggers some async action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;setUserId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;useAff&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;try&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;apiClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getUserProducts&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;
  &lt;span class="n"&gt;liftEffect&lt;/span&gt; &lt;span class="kr"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt;
    &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setUserProfile&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;showError&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;button&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"ghost"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"md"&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="n"&gt;preventDefault&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;setUserId&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="s"&gt;"Clicked"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Failure handling
&lt;/h3&gt;

&lt;p&gt;The situation is not much better than in Scala.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Option&lt;/code&gt; is called &lt;code&gt;Maybe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Error is the the type of JavaScript errors that lives in &lt;code&gt;Effect.Exception&lt;/code&gt;  (cousins of &lt;code&gt;Throwable&lt;/code&gt;). You can throws those via &lt;a href="https://pursuit.purescript.org/packages/purescript-exceptions/6.1.0/docs/Effect.Exception#v:throwException" rel="noopener noreferrer"&gt;&lt;code&gt;throwException&lt;/code&gt;&lt;/a&gt; into &lt;del&gt;&lt;code&gt;IO&lt;/code&gt;&lt;/del&gt;, I mean &lt;code&gt;Effect&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;There is also &lt;code&gt;MonadThrow&lt;/code&gt; and &lt;code&gt;MonadError&lt;/code&gt; that, for example, have &lt;code&gt;throwError&lt;/code&gt; to throw and &lt;a href="https://pursuit.purescript.org/packages/purescript-transformers/6.1.0/docs/Control.Monad.Error.Class#v:try" rel="noopener noreferrer"&gt;&lt;code&gt;try&lt;/code&gt;&lt;/a&gt; to catch errors (for instance, in &lt;code&gt;Effect&lt;/code&gt; and &lt;code&gt;Aff&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Organizing code
&lt;/h3&gt;

&lt;p&gt;There are options for all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s common and convenient to use plain data types and pass things around via records.&lt;/li&gt;
&lt;li&gt;There are mtl classes (see the &lt;a href="https://pursuit.purescript.org/packages/purescript-transformers/6.1.0" rel="noopener noreferrer"&gt;transformers&lt;/a&gt; library).&lt;/li&gt;
&lt;li&gt;There is &lt;a href="https://pursuit.purescript.org/packages/purescript-yoga-om/0.1.0" rel="noopener noreferrer"&gt;yoga-om&lt;/a&gt; — &lt;code&gt;Om&lt;/code&gt; data type (&lt;code&gt;Om ctx errs a&lt;/code&gt;) has a &lt;em&gt;context&lt;/em&gt;, potential &lt;em&gt;errors&lt;/em&gt;, and the &lt;em&gt;value&lt;/em&gt; of the computation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;You know how you have Scala and Java code, than use &lt;code&gt;sbt&lt;/code&gt; (or some other build tool), and it all becomes one bytecode mess that you run or deploy? &lt;/p&gt;

&lt;p&gt;In PureScript world, we &lt;strong&gt;can’t&lt;/strong&gt; get away with using just one tool. &lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;spago&lt;/code&gt; (a PureScript package manager and a build tool) to run and test pure PureScript projects, as well as turn PS code into JS code. For example, we can run &lt;code&gt;spago test&lt;/code&gt; to run our PS tests.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Note that, there is legacy &lt;a href="https://github.com/purescript/spago-legacy" rel="noopener noreferrer"&gt;&lt;code&gt;spago&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/purescript/spago" rel="noopener noreferrer"&gt;&lt;code&gt;spago@next&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But we can’t get far with PureScript alone in the modern web. So.&lt;/p&gt;

&lt;p&gt;We use dependency/package managers, such as &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt;, to install JS packages (both globally and locally). For example, we can install and use &lt;code&gt;react&lt;/code&gt; in our PS project.&lt;/p&gt;

&lt;p&gt;We also need a bundler — another build tool that let’s us bundle everything together (into a single executable file or few files), optimize JavaScript, and produce production files when we are ready to ship. There are multiple options here; the most popular are &lt;code&gt;esbuilt&lt;/code&gt;, &lt;code&gt;webpack&lt;/code&gt;, and &lt;code&gt;parcel&lt;/code&gt; (see &lt;a href="https://github.com/purescript/spago?tab=readme-ov-file#bundle-a-project-into-a-single-js-file" rel="noopener noreferrer"&gt;spago tutorial&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Note that &lt;code&gt;spago&lt;/code&gt; has a &lt;code&gt;bundle&lt;/code&gt; command to bundle the project. Maybe that’s enough for your use case.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Bad news&lt;/strong&gt;: this is just a tip of the iceberg of tools. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good news&lt;/strong&gt;: no need to worry, usually all of it is going to be hidden from you behind npm or yarn scripts. Often, you can get away with limiting your vocabulary to &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;npm start&lt;/code&gt;, &lt;code&gt;npm deploy&lt;/code&gt;, or something along those lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editor
&lt;/h3&gt;

&lt;p&gt;You can use &lt;a href="https://plugins.jetbrains.com/plugin/9738-purescript" rel="noopener noreferrer"&gt;Intellij with PureScript plugin&lt;/a&gt; or any other editor via &lt;a href="https://github.com/purescript/purescript/tree/master/psc-ide" rel="noopener noreferrer"&gt;&lt;code&gt;purs ide&lt;/code&gt;&lt;/a&gt; (an IDE server that comes with compiler) or &lt;a href="https://github.com/nwolverson/purescript-language-server" rel="noopener noreferrer"&gt;PureScript language server&lt;/a&gt; (built on top of IDE server). &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 For details, see the dedicated documentation section on &lt;a href="https://github.com/purescript/documentation/blob/master/ecosystem/Editor-and-tool-support.md" rel="noopener noreferrer"&gt;Editor support&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don’t expect java-level IDE support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Searching for functions
&lt;/h3&gt;

&lt;p&gt;If you’re looking for some function or some data type, you can still use dot completion on a module, but if you don’t know where to look, try &lt;a href="https://pursuit.purescript.org/" rel="noopener noreferrer"&gt;pursuit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also use typed holes, to get compiler suggestions (it also works in the editor).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hole 'custom' has the inferred type

  UserId
  -&amp;gt; Effect
       (Either t0
          { subscriptionId :: SubscriptionId
          , userId :: UserId
          }
       )

You could substitute the hole with one of these values:

  TestTypes.fetchUser         :: UserId
                                 -&amp;gt; Effect
                                      (Either Error
                                         { subscriptionId :: SubscriptionId
                                         , userId :: UserId
                                         }
                                      )

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get help with types as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="kt"&gt;What&lt;/span&gt;&lt;span class="p"&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 plaintext"&gt;&lt;code&gt;Hole 'What' has the inferred type

    { subscriptionId :: SubscriptionId
    , userId :: UserId
    }

  in the following context:

    subscription :: Either Error
                      { subscriptionId :: SubscriptionId
                      , userId :: UserId
                      }
                    -&amp;gt; Effect Subscription
    user :: { subscriptionId :: SubscriptionId
            , userId :: UserId
            }
    userSubscription :: { subscriptionId :: SubscriptionId
                        , userId :: UserId
                        }
                        -&amp;gt; Effect Subscription
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Standard library
&lt;/h3&gt;

&lt;p&gt;Standard library (std module) is called &lt;a href="https://pursuit.purescript.org/packages/purescript-prelude/6.0.1/docs/Prelude" rel="noopener noreferrer"&gt;Prelude&lt;/a&gt; (the &lt;code&gt;Prelude&lt;/code&gt; module comes via the &lt;a href="https://github.com/purescript/purescript-prelude" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-prelude&lt;/code&gt;&lt;/a&gt; library). It has to be explicitly imported.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Prelude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This, for example, imports common type class methods, such as &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt; and &lt;code&gt;pure&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching for libraries and FFI
&lt;/h3&gt;

&lt;p&gt;If you’re looking for a library (a package), you can still poke around pursuit. But if you can’t find anything, there is always a see of JS libraries that can be used from PS. We do this via &lt;em&gt;The Foreign Function Interface (or FFI, for short).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We’ve demonstrated this in the &lt;a href="https://www.youtube.com/watch?v=Vgn5hEVK7lU&amp;amp;ab_channel=ImpurePics" rel="noopener noreferrer"&gt;PureScript + Shadcn video&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Searching and managing dependency versions
&lt;/h3&gt;

&lt;p&gt;You &lt;strong&gt;don’t have to&lt;/strong&gt; search for specific library versions compatible with other libraries. There are  &lt;a href="https://github.com/purescript/spago?tab=readme-ov-file#whats-a-package-set" rel="noopener noreferrer"&gt;lists of package versions that build together&lt;/a&gt;, called a package set. &lt;/p&gt;

&lt;p&gt;Reproducible builds are one of the core principles of &lt;code&gt;spago&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Books and other resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.purescript.org/" rel="noopener noreferrer"&gt;PureScript website&lt;/a&gt; and &lt;a href="https://github.com/purescript/documentation/blob/master/guides/Getting-Started.md" rel="noopener noreferrer"&gt;Getting Started Guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Free &lt;a href="https://book.purescript.org/" rel="noopener noreferrer"&gt;PureScript By Example&lt;/a&gt; Book.&lt;/li&gt;
&lt;li&gt;Blog posts: &lt;a href="https://thomashoneyman.com/articles/" rel="noopener noreferrer"&gt;Thomas Honeyman Articles&lt;/a&gt;, &lt;a href="https://jordanmartinez.github.io/purescript-jordans-reference-site/" rel="noopener noreferrer"&gt;PureScript: Jordan’s Reference&lt;/a&gt;, &lt;a href="https://alethic.art/getting-started/with-purescript" rel="noopener noreferrer"&gt;Mark’s alethic.art&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Community: &lt;a href="https://purescript.org/chat" rel="noopener noreferrer"&gt;PureScript Discord&lt;/a&gt; or &lt;a href="https://discourse.purescript.org/" rel="noopener noreferrer"&gt;PureScript Discourse&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Playground: &lt;a href="https://try.purescript.org/" rel="noopener noreferrer"&gt;try.purescript.org&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>scala</category>
      <category>purescript</category>
      <category>functional</category>
      <category>webdev</category>
    </item>
    <item>
      <title>On “superiority” of (functional) programming and other labels</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Wed, 30 Oct 2024 03:32:26 +0000</pubDate>
      <link>https://forem.com/zelenya/on-superiority-of-functional-programming-and-other-labels-36dk</link>
      <guid>https://forem.com/zelenya/on-superiority-of-functional-programming-and-other-labels-36dk</guid>
      <description>&lt;p&gt;I'm not going to lie. There was a time when I used to believe that. I was convinced I only wanted to work with functional programmers because functional programmers are &lt;em&gt;better&lt;/em&gt; programmers.&lt;/p&gt;

&lt;p&gt;And I know others still think that way. Likewise, some believe that C programmers are better than Rust programmers, devs that use AI tools are better than others, and vice versa.&lt;/p&gt;

&lt;p&gt;Reaching that kind of conclusion takes only a few logical (mis)steps. In my case, it was like this:&lt;/p&gt;

&lt;h2&gt;
  
  
  fp and good code
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;I care a lot about writing good, reliable software&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I consider coding a craft. I want to be productive and write maintainable code that delivers value. I don’t want to do a sloppy job, introduce preventable bugs or tech debt, and get woken up in the middle of the night.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I know that functional programming is a great tool for that&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have years of experience with functional and non-functional languages and suck at the latter. The other day, it took me 3 pull requests (3 deployments to production) to ship a trivial change to a Ruby codebase. Maybe that’s a special case. However, I’m sure I write and read Scala code better and faster than Ruby, PureScript than TypeScript/JavaScript, and so on.&lt;/p&gt;

&lt;p&gt;This misdirected me to a naive conclusion: &lt;em&gt;A programmer who cares about writing good, reliable software should use functional programming.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In other words, if someone doesn’t use FP, they don’t care. Right? Cause, why someone interested in writing good code chooses not to? Why are they choosing to use inferior tools and do a sloppy job?&lt;/p&gt;

&lt;h2&gt;
  
  
  not-fp and good code
&lt;/h2&gt;

&lt;p&gt;Turns out &lt;strong&gt;“I”&lt;/strong&gt; am not the &lt;strong&gt;“programmers”&lt;/strong&gt;. And there are other programmers (and other people).&lt;/p&gt;

&lt;p&gt;Just because a tool helps me — doesn’t mean it helps others. People are different, environments are different, abilities are different, and so on.&lt;/p&gt;

&lt;p&gt;For instance, some people are good at holding many things in their working memory and switching between tasks, but I’m not. When working on something, I easily get distracted by slack messages, switch contexts, and — &lt;em&gt;poof —&lt;/em&gt; completely forget what I was doing. I need functional programming — I need small independent blocks that I can quickly joggle and work with.&lt;/p&gt;

&lt;p&gt;Also, people have different values and preferences. Take, for example, &lt;em&gt;abstraction&lt;/em&gt; and &lt;em&gt;expressiveness&lt;/em&gt; (those are different concepts but related enough). There is plenty of room for choice here. I believe that a typical functional dev is leaning to a greater extent on both. Extracting abstractions, reusing functionality, and refactoring data types, among other things, are completely &lt;strong&gt;different&lt;/strong&gt; experiences in Rust and Haskell. Similarly, handling optionality, errors, lists, and async programming in Scala and Java…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuholdo0bpe8wg5cr7om.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuholdo0bpe8wg5cr7om.jpg" alt="Graph" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you aren’t familiar with those or don’t care for them, the ordinary opinionated programming thing is generics. There are Go, Java generics, and Zig comptime, and there are plenty of programmers who prefer and are productive with each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  fp and bad code
&lt;/h2&gt;

&lt;p&gt;So, there are functional programmers who write good, reliable software, and there are other programmers who write good, reliable software. Which is one thing.&lt;/p&gt;

&lt;p&gt;The other thing is that if we deceive ourselves with generic statements (like I did), it’s easy to forget that there are functional programmers who don’t write good, reliable software. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gp438js2m16ghs5sfqk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4gp438js2m16ghs5sfqk.jpg" alt="Graph" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason I’m chewing on this topic is this other extreme. I haven’t noticed this in my earlier days, but it turns out that quite a number of FP devs just &lt;em&gt;offload their thinking&lt;/em&gt; (or not thinking) onto functional programming, tangential theory, and other standards.&lt;/p&gt;

&lt;p&gt;It’s easy to fall into this kind of attitude: &lt;em&gt;FP is so formal and mathematical and whatever, so let’s just over-rely on it and don’t reason ourselves&lt;/em&gt;. You know? The people who seriously believe that “if it compiles, it works” or “if it’s according to the specification, it’s perfect”. &lt;/p&gt;

&lt;p&gt;Totally shattered my devotion to functional programmers.&lt;/p&gt;

&lt;p&gt;In other words, if someone is doing X, it doesn’t mean they have values associated with X, or X can imply any values in the first place.&lt;/p&gt;




&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OyIVYafHvxI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>functional</category>
    </item>
    <item>
      <title>How to make a quick and pretty PureScript web app</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Tue, 01 Oct 2024 00:10:54 +0000</pubDate>
      <link>https://forem.com/zelenya/how-to-make-a-quick-and-pretty-purescript-web-app-4cl4</link>
      <guid>https://forem.com/zelenya/how-to-make-a-quick-and-pretty-purescript-web-app-4cl4</guid>
      <description>&lt;p&gt;In theory, I’m a full stack developer, but in the last year or two, I’m on the backend, staring at the code, terminal, and google docs  — not tinkering much with UIs (or anything like that).&lt;/p&gt;

&lt;p&gt;But some weeks ago, I built a prototype for a PureScript web app and want to showcase what I did in a &lt;strong&gt;couple of hours&lt;/strong&gt;… I’ve pretty much copy-pasted all of this and spent most of the time scaffolding all the configs and dependencies. &lt;/p&gt;

&lt;p&gt;The idea is to demo how quick it is to have something nice running with PureScript (not single-handedly) and share a minimal interesting project that can be used to play around with PureScript (as well as save myself and other time in the future)&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;For this project, I used PureScript + React + &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind css&lt;/a&gt; + &lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;shadcn/ui components&lt;/a&gt;. I assume you’ve heard of the first two (if not, see &lt;a href="https://youtu.be/GTYgsXTh10Q?si=oTAXxG9P42wv2lpW" rel="noopener noreferrer"&gt;PureScript overview&lt;/a&gt;). The other two are blessings for the copy-paste-driven development.&lt;/p&gt;

&lt;p&gt;Tailwind is a CSS framework that provides &lt;em&gt;classes&lt;/em&gt; for styling components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-medium"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sky-500 dark:text-sky-400"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Some text
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-slate-700 dark:text-slate-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    More text
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Honestly, this extra noise in the markdown was scaring me away before. I decided to try it (for the first time) because I heard it’s supposed to be quite composable and also that’s what shadcn uses.&lt;/p&gt;

&lt;p&gt;From the shadcn website: “&lt;em&gt;Beautifully designed components that you can copy and paste into your apps”.&lt;/em&gt; That’s all I ever wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s see the code
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/Zelenya/purescript-shadcn-tailwind-copypaste" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-shadcn-tailwind-copypaste&lt;/code&gt;&lt;/a&gt; repository also demos a few other things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;routing with &lt;code&gt;routing-duplex&lt;/code&gt; and &lt;code&gt;web-router&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ergonomic FFI with &lt;code&gt;undefined-is-not-a-problem&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;copy-paste with &lt;code&gt;web-clipboard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;basic usage of &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;fetch-yoga-json&lt;/code&gt;, &lt;code&gt;yoga-json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;primitive authentication with local storage (&lt;code&gt;web-storage&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;service/handler pattern&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Vgn5hEVK7lU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>webdev</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Scala is one of the best ways to learn Haskell</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Tue, 17 Sep 2024 04:52:34 +0000</pubDate>
      <link>https://forem.com/zelenya/scala-is-one-of-the-best-ways-to-learn-haskell-12e6</link>
      <guid>https://forem.com/zelenya/scala-is-one-of-the-best-ways-to-learn-haskell-12e6</guid>
      <description>&lt;p&gt;First, a reminder: You DON’T NEED TO learn Haskell — that’s not what I want to talk about. I genuinely want to talk about learning Haskell, and Haskell specifically — not functional programming. &lt;/p&gt;

&lt;p&gt;The following might interest you if you want to get into Haskell for personal reasons (if you think it’s cool, well-paid, or whatever). If not — idk…&lt;/p&gt;




&lt;p&gt;📹 Hate reading articles? Check out &lt;a href="https://youtu.be/_FM_y2gIj0Y" rel="noopener noreferrer"&gt;the complementary video&lt;/a&gt;, which covers the same content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Haskell is tough to learn
&lt;/h2&gt;

&lt;p&gt;People constantly report about their frustration with learning Haskell. Working professionals already have some experience and expectations from using a language. For example, a Java developer can pick up Go and carry over most of their knowledge, while Haskell can crash all their assumptions about programming. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;How is it that I know how to connect to databases, serve http, make decent uis, or all the other cool stuff — but then I can’t simply print a variable in Haskell or get the value out of some box?!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can blame it on education, learning resources, skills, or whatever… but the thing is: there are &lt;strong&gt;too many things to joggle in Haskell&lt;/strong&gt;. Imagine a Java developer. If they want to learn Go, they need to learn new concurrency mechanisms, pay some attention to syntax (still C family), unlearn inheritance, resist using abstract factories, get used to a couple of other things, and that’s pretty much it (&lt;em&gt;I know, it’s a bit oversimplified&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;But then imagine them learning Haskell — now there are more unfamiliar faces: laziness, purity, IO, type classes, immutable collections, entirely different syntax, etc. — and see them getting crashed by the balls.&lt;/p&gt;

&lt;h2&gt;
  
  
  One step at a time
&lt;/h2&gt;

&lt;p&gt;Scala is a multi-paradigm language that allows you to tame this gap and learn one ball at a time.&lt;/p&gt;

&lt;p&gt;The most stereotypical example is starting with Scala as a better Java (a bit of new syntax and constructs) and then building on top of that: introducing immutable collections, other immutability, purity, type classes, IO, and so on.&lt;/p&gt;

&lt;p&gt;If you don’t know how to do something in a “functional” way, do what you know until you learn how: write a for loop, print in the middle whatever you want, throw an exception — it’s your life, don’t let anyone tell you what to do. You’ll eventually figure it all out.&lt;/p&gt;

&lt;p&gt;And then, at some point, you “just” get familiar with Haskell’s syntax and laziness, and you're good to go. It’s quite enough to contribute at a middle or even senior level. Yeah, there is still plenty to learn to be proficient. There is always going to be something to learn with Haskell.&lt;/p&gt;

&lt;p&gt;The best part about this flow is it can be done at a personal pace. For instance, you can be productive for years with basic Scala + immutability + ADTs without fully grokking type classes and using IO, then grok type classes and be productive with that, and so on… And if you want to deeply understand the concept before moving to the next one, you can do it too. Good luck doing that with Haskell directly.&lt;/p&gt;

&lt;p&gt;There is a reason that Scala’s logos is a ladder. &lt;em&gt;(It’s a joke; please don’t quote me on that).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  No silver bullet
&lt;/h2&gt;

&lt;p&gt;This way of learning Haskell is not a silver bullet — it’s just &lt;strong&gt;one&lt;/strong&gt; path, which I think is worth considering. It comes naturally to some, judging by dozens of people I know who learned Haskell this way. But might seem unintuitive or even stupid to others.&lt;/p&gt;

&lt;p&gt;Sure, if you’re taking your time studying Haskell in school, it’s a whole different thing. But if you’re already working in the industry, want to invest your free time into learning Haskell and Haskell books and courses don’t work for you (because they’re either too long and tedious or jump over the concepts, hand-wave, and tell you to wait for explanation in later chapters), consider the Scala path.&lt;/p&gt;

&lt;p&gt;Also, Scala is just an example I’m confident with. I guess learning via OCaml might be close enough. I can’t vouch for it — I don’t know anyone who learned Haskell via OCaml (not because they don’t exist, but because they are out of my bubbles). Something like Gleam or Roc could be good as well…&lt;/p&gt;

&lt;p&gt;Also, if you have Rust experience, you can jump to Haskell right away because the gap is smaller. But I wouldn’t recommend learning Rust just to learn Haskell, though…&lt;/p&gt;

&lt;p&gt;And if you come with a JavaScript background, PureScript or Elm is a good pitstop before trying Haskell.&lt;/p&gt;

&lt;p&gt;You have to decide for yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A metaphor
&lt;/h2&gt;

&lt;p&gt;Look at it this way. Imagine you want to learn to be an artist.&lt;/p&gt;

&lt;p&gt;You can start &lt;strong&gt;painting&lt;/strong&gt; (with whatever medium), where you must joggle shapes, values, colors, light, and shadow. I’m not even talking about other fundamentals (like subject, composition, or perspective). This is just the minimum, and it could already be overwhelming.&lt;/p&gt;

&lt;p&gt;That’s why lots of people start with something like drawing with &lt;strong&gt;charcoal&lt;/strong&gt; and restrict to basic shapes and values. For starters, you don’t have to worry about colors or try to understand shadows — just treat everything as shapes. And later, add perspective, light, complex shapes, or whatever you like.&lt;/p&gt;

&lt;p&gt;And, of course, some people directly pick up painting without drawing experience (and don’t get overwhelmed).&lt;/p&gt;

</description>
      <category>scala</category>
      <category>haskell</category>
      <category>functional</category>
    </item>
    <item>
      <title>Scala for Haskell developers</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Tue, 27 Aug 2024 03:18:50 +0000</pubDate>
      <link>https://forem.com/zelenya/scala-for-haskell-developers-1fon</link>
      <guid>https://forem.com/zelenya/scala-for-haskell-developers-1fon</guid>
      <description>&lt;p&gt;So, you have some &lt;strong&gt;Haskell experience&lt;/strong&gt; and want (or need to) write &lt;strong&gt;Scala code&lt;/strong&gt;. The following is a rough map with the main differences, similarities, major gotchas, and most useful resources. &lt;/p&gt;

&lt;p&gt;📹 Context: subjective-&lt;strong&gt;production&lt;/strong&gt;-backend experience, web apps, microservices, shuffling jsons, and all that stuff.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🥈 &lt;strong&gt;Scala 2 and Scala 3.&lt;/strong&gt; In 2024, some projects still haven’t upgraded to Scala 3. Unless it includes the company you’re working for, you &lt;strong&gt;don’t need to&lt;/strong&gt; &lt;strong&gt;worry&lt;/strong&gt; about Scala 2.&lt;/p&gt;

&lt;p&gt;Most of the stuff here applies to both; we lean towards Scala 3 and explicitly describe both if there is a big difference.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;📹 Hate reading articles? Check out &lt;a href="https://youtu.be/SpFs9rM1Mcg" rel="noopener noreferrer"&gt;the complementary video&lt;/a&gt;, which covers the same content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic syntax and attitude
&lt;/h2&gt;

&lt;p&gt;You should pick up syntax by yourself, but here are the things you should conquer first:&lt;/p&gt;

&lt;h3&gt;
  
  
  Driving on the wrong side of the road
&lt;/h3&gt;

&lt;p&gt;Forget about reading code from right to left. You’re not in Haskell land.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;errorMessage&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scala, similar to Java, often chains from left to right:&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="c1"&gt;// read from left to right&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&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="py"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the same time, you will often encounter code like this:&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;fee&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&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="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="py"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&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;faa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order and syntax are different due to using &lt;a href="https://docs.scala-lang.org/tour/basics.html#methods" rel="noopener noreferrer"&gt;methods&lt;/a&gt; and not functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Methods
&lt;/h3&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;fee&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&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="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="py"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&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;faa&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;errorMessage&lt;/code&gt; is a normal method on a class (&lt;code&gt;Error&lt;/code&gt;) — typical OOP.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Left&lt;/code&gt; is a constructor (&lt;code&gt;Either&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;delay&lt;/code&gt; is a static method on a &lt;a href="https://docs.scala-lang.org/tour/singleton-objects.html" rel="noopener noreferrer"&gt;singleton object&lt;/a&gt; (&lt;code&gt;IO&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pure&lt;/code&gt; is an &lt;a href="https://docs.scala-lang.org/scala3/book/ca-extension-methods.html" rel="noopener noreferrer"&gt;extension method&lt;/a&gt; (for anything with an &lt;code&gt;Applicative&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first variant particularly relies on &lt;a href="https://docs.scala-lang.org/scala3/book/ca-extension-methods.html" rel="noopener noreferrer"&gt;extension methods&lt;/a&gt; to get this consistent syntax:&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;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;errorMessage&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="py"&gt;pure&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s not as complicated as it might appear. &lt;/p&gt;

&lt;p&gt;Just one more thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functions and methods
&lt;/h3&gt;

&lt;p&gt;In Scala, there are &lt;a href="https://docs.scala-lang.org/tour/basics.html#functions" rel="noopener noreferrer"&gt;Functions&lt;/a&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;val&lt;/span&gt; &lt;span class="nv"&gt;function1&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="k"&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;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can convert methods to 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;class&lt;/span&gt; &lt;span class="nc"&gt;Tmp&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="kt"&gt;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;s:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;length&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;function2&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;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tmp&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;method&lt;/span&gt;

&lt;span class="nc"&gt;Tmp&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="nf"&gt;function1&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="nf"&gt;function2&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🥈  In Scala 2, it’s slightly more verbose: &lt;code&gt;new Tmp().method _&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even if you miss functions, get used to declaring methods (and when needed use them as functions). &lt;em&gt;The transitions are so seamless that I usually don’t think about them.&lt;/em&gt; And if you are new to OOP, good luck. See the official docs, write/read code, and give it some time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function and method signatures
&lt;/h3&gt;

&lt;p&gt;Functions are expressions and their types can be (often) inferred:&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;function2&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Tmp&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;method&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;nope&lt;/span&gt; &lt;span class="k"&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;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you declare a non-zero-arity methods, you can’t omit the types of 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;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the return type is optional (it’s usually a bad practice):&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;method&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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="nv"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The unit return type (doesn’t return any value):&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;helloWorld&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&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;"Hello, World!"&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;blockquote&gt;
&lt;p&gt;⚠️ It’s not functional but something you might encounter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Scala, we can use &lt;a href="https://docs.scala-lang.org/tour/default-parameter-values.html" rel="noopener noreferrer"&gt;default parameter values&lt;/a&gt;, &lt;a href="https://docs.scala-lang.org/tour/named-arguments.html" rel="noopener noreferrer"&gt;named arguments&lt;/a&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;helloWorld&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greet&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="s"&gt;"Hello"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&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="s"&gt;"World"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&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="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"$greet, $name!"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;helloWorld&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&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;and &lt;a href="https://docs.scala-lang.org/tour/multiple-parameter-lists.html" rel="noopener noreferrer"&gt;multiple paramater lists&lt;/a&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;helloWorld&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greet&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;name&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;alias&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;Unit&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;blockquote&gt;
&lt;p&gt;💡 The &lt;code&gt;???&lt;/code&gt; is &lt;em&gt;almost&lt;/em&gt; like &lt;code&gt;undefined&lt;/code&gt; (only it’s not lazy and not type-inference friendly).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Names don’t matter?
&lt;/h3&gt;

&lt;p&gt;Scala community has less tolerance for operators.&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;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&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;Result&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; 
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;findSubscription&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;subscriptionId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nv"&gt;subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;fold&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;gt;&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;withDiscount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’re some in DSLs, but there no &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt;, there is &lt;code&gt;map&lt;/code&gt;; there is no &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; or &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt; , but there are &lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;mapN&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="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;some&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;flatMap&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;toIntOption&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Some(1)&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="n"&gt;some&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;mapN&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;_&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// Some(3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is &lt;code&gt;traverse&lt;/code&gt; but no &lt;code&gt;mapM&lt;/code&gt;, see either &lt;code&gt;traverse&lt;/code&gt; or &lt;code&gt;foreach&lt;/code&gt;. &lt;em&gt;This depends on the library and we’ll talk about this later.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Friendly advice: also get familiar with &lt;code&gt;flatTap&lt;/code&gt;, &lt;code&gt;tap&lt;/code&gt;, and alike.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Basic concepts and fp
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Function composition&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Function composition&lt;/strong&gt; isn’t common. There are ways to do it (e.g., there is &lt;a href="https://www.scala-lang.org/api/current/scala/Function1.html#compose-51" rel="noopener noreferrer"&gt;&lt;code&gt;compose&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://www.scala-lang.org/api/current/scala/Function1.html#andThen-51" rel="noopener noreferrer"&gt;&lt;code&gt;andThen&lt;/code&gt;&lt;/a&gt;), but nobody does it (e.g., currying and type inference aren’t helping).&lt;/p&gt;

&lt;h3&gt;
  
  
  Currying
&lt;/h3&gt;

&lt;p&gt;Similar here. You can curry a function but rarely want to or need to.&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;helloWorld&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greet&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;name&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;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"$greet, $name!"&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;one&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;helloWorld&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;curried&lt;/span&gt; &lt;span class="c1"&gt;// : String =&amp;gt; String =&amp;gt; String&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;two&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;one&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// : String =&amp;gt; String&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;res&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;two&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// Hello, World!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because, for instance, you can partially apply “normal” scala functions/methods:&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;two&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;helloWorld&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&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;// : String =&amp;gt; String&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;res&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;two&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"World"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// Hello, World!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a relevant note, get familiar with tuples and function parameters (and how they play and don’t play together).&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;cache&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;empty&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;Int&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;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="k"&gt;:&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="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;span class="c1"&gt;// This works in Scala 2 and Scala 3&lt;/span&gt;
&lt;span class="nv"&gt;cache&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="n"&gt;foo&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;bar&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;i&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt;
&lt;span class="c1"&gt;// This works only in Scala 3&lt;/span&gt;
&lt;span class="nv"&gt;cache&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="n"&gt;bar&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🥈  In Scala 2, there are cases when you need to be explicit (see &lt;code&gt;tupled&lt;/code&gt;) and use more explicit parenthesis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Purity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Scala is not Haskell. For example, you can add a &lt;code&gt;println&lt;/code&gt; ✨ &lt;em&gt;anywhere&lt;/em&gt; ✨.&lt;/p&gt;

&lt;p&gt;You should use a linter or an alternative way to enable recommended compiler options for &lt;em&gt;fp scala&lt;/em&gt;. For example, &lt;a href="https://github.com/typelevel/sbt-tpolecat" rel="noopener noreferrer"&gt;sbt-tpolecat&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Laziness&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you want a lazy variable, see &lt;code&gt;lazy val&lt;/code&gt;. If you want a lazy list, see standard library &lt;code&gt;LazyList&lt;/code&gt;  or alternatives in other libraries (for example, &lt;a href="https://fs2.io/#/" rel="noopener noreferrer"&gt;fs2&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;However, if you want another kind of laziness: make some thunks, write recursion, or whatever, it’s not that straightforward — beware of stack (safety).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See cats-effect &lt;code&gt;IO&lt;/code&gt; and &lt;code&gt;ZIO&lt;/code&gt; (we cover &lt;code&gt;IO&lt;/code&gt; later).&lt;/li&gt;
&lt;li&gt;See cats &lt;a href="https://typelevel.org/cats/datatypes/eval.html" rel="noopener noreferrer"&gt;&lt;code&gt;Eval&lt;/code&gt;&lt;/a&gt; data type (or other alternatives).&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;@tailrec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;tailRecM&lt;/code&gt; and other ways to trampoline.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Beware of the standard library Futures.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Modules and Imports&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Good news: Scala has first-class modules and you don’t need to qualify imports or prefix fields. And you can &lt;a href="https://docs.scala-lang.org/tour/inner-classes.html" rel="noopener noreferrer"&gt;nest&lt;/a&gt; them!&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;class&lt;/span&gt; &lt;span class="nc"&gt;One&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Two:&lt;/span&gt;
    &lt;span class="kt"&gt;val&lt;/span&gt; &lt;span class="kt"&gt;three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad news: you have to get familiar with classes, objects, companion objects, and how to choose where to put your functions.&lt;/p&gt;

&lt;p&gt;Terrible news: you still have to worry about imports because they can affect the program’s behavior (we talk about this (&lt;code&gt;implicits&lt;/code&gt;) later).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Standard library&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Scala comes with a &lt;a href="https://docs.scala-lang.org/overviews/collections-2.13/overview.html" rel="noopener noreferrer"&gt;bundle&lt;/a&gt; of immutable collections (&lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Vector&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, etc.). In the beginning, pay attention, ensure that you are using immutable versions, and stay away from overgeneralized classes, like &lt;code&gt;Seq&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, be open-minded — in many cases, Scala has better methods/combinators than you might expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Equality
&lt;/h3&gt;

&lt;p&gt;In Scala 2, multiversal equality was hell for me:&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="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Scala 3, it’s not allowed:&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;^^^^^^^^^^^&lt;/span&gt;
&lt;span class="nc"&gt;Values&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;compared&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But out of the box, you can still shoot yourself:&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;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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="nf"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;B&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can &lt;a href="https://docs.scala-lang.org/scala3/book/ca-multiversal-equality.html#allowing-the-comparison-of-class-instances" rel="noopener noreferrer"&gt;disable&lt;/a&gt; it with the &lt;code&gt;strictEquality&lt;/code&gt; compiler flag:&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.language.strictEquality&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;derives&lt;/span&gt; &lt;span class="nc"&gt;CanEqual&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;derives&lt;/span&gt; &lt;span class="nc"&gt;CanEqual&lt;/span&gt;

&lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nf"&gt;A&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;B&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// ^^^^^^^^^^^&lt;/span&gt;
&lt;span class="c1"&gt;// Values of types A and B cannot be compared&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Type inference
&lt;/h3&gt;

&lt;p&gt;When I was thinking about this guide a couple of years ago, I thought it was going to be the beefiest chapter. Luckily, Scala 3 is pretty good at type inference. &lt;/p&gt;

&lt;p&gt;And yeah, it’s still not Haskell and sometimes you need to help 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;val&lt;/span&gt; &lt;span class="nv"&gt;id&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="c1"&gt;// error:&lt;/span&gt;
&lt;span class="c1"&gt;// Missing parameter type&lt;/span&gt;
&lt;span class="c1"&gt;// I could not infer the type of the parameter a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;id&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="k"&gt;=&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;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;idInt&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could come up during refactoring. For example, this is fine&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;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&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;f1&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this doesn’t compile (&lt;code&gt;empty&lt;/code&gt; should be helped):&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;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&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;s1&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;empty&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;f1&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But once again, don’t worry, it’s mostly good. For instance, using monad transformers used to be type-inference hell — in Scala 3, it’s fine:&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;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&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;Result&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="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;EitherT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;right&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fetchUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nc"&gt;EitherT&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;findSubscription&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;subscriptionId&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;EitherT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;right&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Log message"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;withDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="o"&gt;)).&lt;/span&gt;&lt;span class="py"&gt;valueOr&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;gt;&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🥈 If you’re on Scala 2, you might need to get in the habit of annotating intermediate values. And just be gentler to the compiler!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Union types
&lt;/h3&gt;

&lt;p&gt;Union types are great.&lt;/p&gt;

&lt;p&gt;But even union types need an occasional help:&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;foo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EitherT&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;MyError&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="k"&gt;for&lt;/span&gt; 
  &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;thisThrowsA&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// At least one needs to be explicitly casted&lt;/span&gt;
  &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nf"&gt;thisThrowsB&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="py"&gt;leftWiden&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;MyError&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s"&gt;"result"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotFound&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BadRequest&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;MyError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NotFound&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;BadRequest&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;thisThrowsA&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EitherT&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;NotFound&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;def&lt;/span&gt; &lt;span class="nf"&gt;thisThrowsB&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;EitherT&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;BadRequest&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Product types
&lt;/h3&gt;

&lt;p&gt;Product types aren’t bad either. You use case classes:&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;case&lt;/span&gt; &lt;span class="k"&gt;class&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;name&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;subscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&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="s"&gt;"Kat"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"paypal-7"&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;name&lt;/span&gt; &lt;span class="c1"&gt;// Kat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which come with a &lt;code&gt;copy&lt;/code&gt; method to modify fields:&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;resu&lt;/span&gt; &lt;span class="k"&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;copy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"apple-12"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And 95% of the time it’s enough. When you need to, you can use optics (for example, via &lt;a href="https://www.optics.dev/Monocle/" rel="noopener noreferrer"&gt;monocle&lt;/a&gt;) or data transformations via libraries like &lt;a href="https://chimney.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;chimney&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sum types
&lt;/h3&gt;

&lt;p&gt;Sum types are a bit more awkward.&lt;/p&gt;

&lt;p&gt;In Scala 2, we used to model sum types with &lt;code&gt;sealed&lt;/code&gt; &lt;code&gt;trait&lt;/code&gt; hierarchies:&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;sealed&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Anon&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We used to do the same for enums (with some boilerplate) or use the &lt;a href="https://github.com/lloydmeta/enumeratum" rel="noopener noreferrer"&gt;enumeratum&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;sealed&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Anon&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;🤔 &lt;a href="https://github.com/lloydmeta/enumeratum" rel="noopener noreferrer"&gt;enumeratum&lt;/a&gt; was made as an alternative to Scala-2-built-in &lt;code&gt;Enumeration&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Scala 3, we have nicer &lt;a href="https://docs.scala-lang.org/scala3/reference/enums/enums.html" rel="noopener noreferrer"&gt;enums&lt;/a&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="n"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Anon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which are general enough to support ADTs:&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="n"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;Role&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;Customer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;userId:&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="kt"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;Admin&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Anon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Some still use &lt;a href="https://github.com/lloydmeta/enumeratum" rel="noopener noreferrer"&gt;enumeratum&lt;/a&gt; with Scala 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Newtypes
&lt;/h3&gt;

&lt;p&gt;Newtypes are even more awkward.&lt;/p&gt;

&lt;p&gt;In Scala 2, we used &lt;a href="https://docs.scala-lang.org/overviews/core/value-classes.html" rel="noopener noreferrer"&gt;Value Classes&lt;/a&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;class&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&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;value&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;extends&lt;/span&gt; &lt;span class="nc"&gt;AnyVal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scala 3 has &lt;a href="https://docs.scala-lang.org/scala3/book/types-opaque-types.html" rel="noopener noreferrer"&gt;Opaque Types&lt;/a&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="n"&gt;opaque&lt;/span&gt; &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the thing is, by themselves, both aren’t ergonomic and require boilerplate. So, you need either embrace manual wrapping, unwrapping, and other boilerplate OR use one of the many newtype libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern matching
&lt;/h3&gt;

&lt;p&gt;There shouldn’t be anything too surprising about pattern matching (just watch out for parenthesis):&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;getName&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;Option&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;:&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;user&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&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;name&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;if&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;nonEmpty&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"anon"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you should know where &lt;a href="https://docs.scala-lang.org/tour/pattern-matching.html" rel="noopener noreferrer"&gt;pattern matching&lt;/a&gt; comes from. Scala allows pattern matching on objects with an &lt;code&gt;unapply&lt;/code&gt; method. Case classes (like &lt;code&gt;User&lt;/code&gt;) and enums (like &lt;code&gt;Role&lt;/code&gt;) possess it out of the box. But if we need to, we can provide additional &lt;code&gt;unapply&lt;/code&gt; methods or implement &lt;code&gt;unapply&lt;/code&gt; for other classes.&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;class&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&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;value&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;extends&lt;/span&gt; &lt;span class="nc"&gt;AnyVal&lt;/span&gt;

&lt;span class="k"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="kt"&gt;unapply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;id:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="kt"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&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="nv"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;lastOption&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nc"&gt;SubscriptionId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"paypal-12"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;SubscriptionId&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="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;_&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"oops"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 See &lt;a href="https://docs.scala-lang.org/tour/extractor-objects.html" rel="noopener noreferrer"&gt;extractor objects&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Polymorphism
&lt;/h2&gt;

&lt;p&gt;Type parameters are confined in square brackets:&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;filter&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="n"&gt;list&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;A&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Boolean&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;A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
  &lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;filter&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Square brackets are also used for type applications:&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;x&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;empty&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type classes, implicits and givens
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I don’t think it makes sense for me to go into too much detail here, especially, given the differences between Scala 2 and Scala 3.&lt;/em&gt; Just a few things you should put into your hippocampus:&lt;/p&gt;

&lt;p&gt;In Scala 2, instance declarations are implicits:&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;val&lt;/span&gt; &lt;span class="nv"&gt;example&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Option&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;pure&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="n"&gt;a&lt;/span&gt;&lt;span class="k"&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="kt"&gt;Option&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;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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;flatMap&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;, &lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;ma&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&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="n"&gt;f&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;ma&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&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;In Scala 3, &lt;a href="https://docs.scala-lang.org/scala3/book/ca-type-classes.html" rel="noopener noreferrer"&gt;type classes&lt;/a&gt; are more integrated; you write &lt;code&gt;given&lt;/code&gt; instances:&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="n"&gt;given&lt;/span&gt; &lt;span class="nc"&gt;Monad&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;with&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;pure&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="n"&gt;a&lt;/span&gt;&lt;span class="k"&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="kt"&gt;Option&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;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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;flatMap&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;, &lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;ma&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&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="n"&gt;f&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; 
    &lt;span class="n"&gt;ma&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;None&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;In Scala 2 and Scala 3, &lt;strong&gt;context&lt;/strong&gt; looks something like this:&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="c1"&gt;//     ................&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&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;A&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;fa&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;A&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;A&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="k"&gt;for&lt;/span&gt; 
    &lt;span class="n"&gt;a1&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fa&lt;/span&gt;
    &lt;span class="n"&gt;a2&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;fa&lt;/span&gt;
  &lt;span class="nf"&gt;yield&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;code&gt;F[_]&lt;/code&gt; and &lt;code&gt;F[A]&lt;/code&gt; in Scala is as conventional as &lt;code&gt;m a&lt;/code&gt; in Haskell.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sometimes, in Scala 2, they look like this:&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;foo&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;A&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;fa&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;A&lt;/span&gt;&lt;span class="o"&gt;])(&lt;/span&gt;&lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="nc"&gt;Monad&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Monad&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;A&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="o"&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Instances
&lt;/h3&gt;

&lt;p&gt;It’s common to put instances into companion objects:&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;case&lt;/span&gt; &lt;span class="k"&gt;class&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;name&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;subscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&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;User&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;implicit&lt;/span&gt; &lt;span class="kt"&gt;val&lt;/span&gt; &lt;span class="kt"&gt;codec:&lt;/span&gt; &lt;span class="kt"&gt;Codec&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;=&lt;/span&gt; &lt;span class="n"&gt;deriveCodec&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;Another place to look for instances is objects named &lt;code&gt;implicits&lt;/code&gt;, for 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;my.something.implicits._&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that you have to remember what to import, and imports technically affect the logic of the program. In application code, it used to be somewhat common but seems to be less popular. It’s still the way to get instances for libraries that integrate with other libraries. For example, &lt;a href="https://iltotore.github.io/iron/docs/modules/circe.html" rel="noopener noreferrer"&gt;iron + circe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, in Scala 3, there is a special &lt;a href="https://docs.scala-lang.org/scala3/reference/contextual/given-imports.html" rel="noopener noreferrer"&gt;form of import&lt;/a&gt; for given instances:&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;my.something.given&lt;/span&gt; &lt;span class="c1"&gt;// Scala 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 Don’t forget to read more about implicits or givens on your own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Deriving (from library user perspective)
&lt;/h3&gt;

&lt;p&gt;In Scala 2, the most popular ways to get instances are automatic and semi-automatic derivations.&lt;/p&gt;

&lt;p&gt;Automatic derivation is when you import something and “magically” get all the instances and functionality; for example, &lt;a href="https://circe.github.io/circe/codecs/auto-derivation.html" rel="noopener noreferrer"&gt;circe json decoders&lt;/a&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;import&lt;/span&gt; &lt;span class="nn"&gt;io.circe.generic.auto._&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semi-automatic derivation is a bit more explicit, &lt;a href="https://circe.github.io/circe/codecs/semiauto-derivation.html" rel="noopener noreferrer"&gt;for example&lt;/a&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;import&lt;/span&gt; &lt;span class="nn"&gt;io.circe.generic.semiauto._&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;codec&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Codec&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;=&lt;/span&gt; &lt;span class="n"&gt;deriveCodec&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;Scala 3 has &lt;a href="https://docs.scala-lang.org/scala3/reference/contextual/derivation.html" rel="noopener noreferrer"&gt;type class derivation&lt;/a&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;case&lt;/span&gt; &lt;span class="k"&gt;class&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;name&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;subscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
  &lt;span class="n"&gt;derives&lt;/span&gt; &lt;span class="nc"&gt;ConfiguredCodec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you can still use semi-auto derivations with Scala 3 (when needed):&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;User&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="kt"&gt;given&lt;/span&gt; &lt;span class="kt"&gt;Codec&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;=&lt;/span&gt; &lt;span class="n"&gt;deriveCodec&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;Consult with the docs of concrete libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meta Programming
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;There are “experimental” macros in Scala 2 and &lt;a href="https://docs.scala-lang.org/scala3/reference/metaprogramming/index.html" rel="noopener noreferrer"&gt;multiple features&lt;/a&gt; in Scala 3.&lt;/li&gt;
&lt;li&gt;There is &lt;a href="https://github.com/milessabin/shapeless" rel="noopener noreferrer"&gt;shapeless&lt;/a&gt; (for scrap-your-boilerplate-like generic programming) for Scala 2 and built-in “shapeless” mechanism in Scala 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deriving (from library author perspective)
&lt;/h3&gt;

&lt;p&gt;In Scala 2, it’s common to use &lt;a href="https://github.com/milessabin/shapeless" rel="noopener noreferrer"&gt;shapeless&lt;/a&gt; and &lt;a href="https://github.com/softwaremill/magnolia" rel="noopener noreferrer"&gt;magnolia&lt;/a&gt; for typeclass derivation.&lt;/p&gt;

&lt;p&gt;Scala 3 has built-in low level &lt;a href="https://docs.scala-lang.org/scala3/reference/contextual/derivation.html" rel="noopener noreferrer"&gt;derivation&lt;/a&gt;. It’s still common to use shapeless and magnolia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Failure handling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Idiomatic Scala code does not use &lt;code&gt;null&lt;/code&gt;.  Don’t worry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Either&lt;/code&gt; is &lt;code&gt;Either&lt;/code&gt;, &lt;code&gt;Maybe&lt;/code&gt; is called &lt;code&gt;Option&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You might see &lt;a href="https://www.scala-lang.org/api/current/scala/util/Try.html" rel="noopener noreferrer"&gt;&lt;code&gt;Try&lt;/code&gt;&lt;/a&gt; here and there.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;Throwable&lt;/code&gt; (cousin of &lt;code&gt;Exception&lt;/code&gt; and &lt;code&gt;SomeExceptions&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For everything else, see what your stack/libraries of choice have in terms of failure handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styles and flavors
&lt;/h3&gt;

&lt;p&gt;There existed a lot of different &lt;em&gt;scalas&lt;/em&gt; throughout the years. In 2024, &lt;em&gt;fp-leaning&lt;/em&gt; &lt;em&gt;industry-leaning&lt;/em&gt; scala converges into two: &lt;a href="https://typelevel.org/" rel="noopener noreferrer"&gt;typelevel&lt;/a&gt; and &lt;a href="https://zio.dev/overview/getting-started" rel="noopener noreferrer"&gt;zio&lt;/a&gt; stacks. Roughly speaking, both come with their own standard library (prelude), IO runtime, &lt;strong&gt;concurrency&lt;/strong&gt;, libraries, and best practices.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 Scala’s standard library is quite functional, but not functional enough. That’s why we have these auxiliary ecosystems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Even more roughly speaking:&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you’re leaning towards using mtl/transformers, see &lt;a href="https://typelevel.org/" rel="noopener noreferrer"&gt;typelevel&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you’re leaning towards using app monads with “baked-in” &lt;code&gt;EitherT&lt;/code&gt; and &lt;code&gt;ResourceT&lt;/code&gt;, see &lt;a href="https://zio.dev/overview/getting-started" rel="noopener noreferrer"&gt;zio&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was a moment when people used free and effect system in production Scala code, but it sucked. So, I don’t think anyone uses either in prod these days. Some library authors still use free.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 There is a hype train forming around &lt;em&gt;“direct-style”&lt;/em&gt; Scala. Actually, there are multiple &lt;em&gt;trains&lt;/em&gt; — because the term is so ambiguous — multiple styles packaged and sold under the same name. If you’re curious, look into it yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you get an “fp” scala job (around 2024), the newer services are going to be written using typelevel or zio (and there probably going to be legacy code in other styles).&lt;/p&gt;

&lt;h3&gt;
  
  
  Typelevel / cats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://typelevel.org/cats/" rel="noopener noreferrer"&gt;cats&lt;/a&gt; and &lt;a href="https://github.com/typelevel/cats-effect/" rel="noopener noreferrer"&gt;cats-effect&lt;/a&gt; are the core of the &lt;a href="https://typelevel.org/" rel="noopener noreferrer"&gt;typelevel&lt;/a&gt; stack&lt;/li&gt;
&lt;li&gt;the other two pillars are &lt;a href="https://github.com/typelevel/fs2" rel="noopener noreferrer"&gt;fs2&lt;/a&gt;, and &lt;a href="https://github.com/http4s/http4s" rel="noopener noreferrer"&gt;http4s&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;the other gotos are &lt;a href="https://github.com/circe/circe" rel="noopener noreferrer"&gt;circe&lt;/a&gt; for json and &lt;a href="https://github.com/tpolecat/doobie" rel="noopener noreferrer"&gt;doobie&lt;/a&gt; for databases&lt;/li&gt;
&lt;li&gt;and many others: &lt;a href="https://github.com/typelevel/kittens" rel="noopener noreferrer"&gt;kittens&lt;/a&gt;, &lt;a href="https://typelevel.org/cats-mtl/" rel="noopener noreferrer"&gt;cats-mtl&lt;/a&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 Note that nothing stops you from using alternative libraries; especially, if they provide required instances or interoperability/conversions. For example, it seems common to use &lt;a href="https://tapir.softwaremill.com/en/latest/" rel="noopener noreferrer"&gt;&lt;code&gt;tapir&lt;/code&gt;&lt;/a&gt; instead (on top of) &lt;code&gt;http4s&lt;/code&gt; for writing http servers in the last years. Tapir integrates with all major Scala stacks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s common to organize code via “tagless final”:&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;Subscription&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;fetchSubscription&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&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;Subscription&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;revokeSubscription&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&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;def&lt;/span&gt; &lt;span class="nf"&gt;findSubscription&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UserId&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;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserId&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;It’s common to tie your app together via &lt;a href="https://typelevel.org/cats-effect/docs/std/resource" rel="noopener noreferrer"&gt;&lt;code&gt;Resource&lt;/code&gt;&lt;/a&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;server&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;Resource&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;, &lt;span class="kt"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;resource&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;Tracing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;makeLogger&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;logLevel&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;HttpClientBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;build&lt;/span&gt;
    &lt;span class="n"&gt;redis&lt;/span&gt;  &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;Redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;kafka&lt;/span&gt;  &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;KafkaConsumer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;     &lt;span class="k"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="nv"&gt;Postgres&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;withConnectionPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;config&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;resource&lt;/span&gt;
    &lt;span class="n"&gt;httpApp&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Business&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kafka&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nv"&gt;HttpServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;make&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;port&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;host&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpApp&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s common to write business logic and organize control flows via fs2 streams:&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;fs2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Stream&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;eval&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fetchSubscriptions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUri&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;evalTap&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;gt;&lt;/span&gt; &lt;span class="nv"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fetched subscriptions..."&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="n"&gt;parseSubscriptions&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;unNone&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;parEvalMapUnordered&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)(&lt;/span&gt;&lt;span class="nf"&gt;withMoreData&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baseUri&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;h3&gt;
  
  
  ZIO
&lt;/h3&gt;

&lt;p&gt;ZIO &lt;a href="https://zio.dev/ecosystem/" rel="noopener noreferrer"&gt;ecosystem&lt;/a&gt; comes with a lot of batteries. &lt;a href="https://zio.dev/reference/core/zio/" rel="noopener noreferrer"&gt;&lt;code&gt;ZIO[R, E, A]&lt;/code&gt;&lt;/a&gt; is a core data type. &lt;a href="https://zio.dev/overview/basic-operations" rel="noopener noreferrer"&gt;See usage&lt;/a&gt; (it’s the way to organize the code, deal with resources/scopes, and control flows).&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;You can use &lt;a href="https://get-coursier.io/" rel="noopener noreferrer"&gt;coursier&lt;/a&gt; to install Scala tooling ghcup-style.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build tools
&lt;/h3&gt;

&lt;p&gt;I’ve never used anything but &lt;a href="https://www.scala-sbt.org/" rel="noopener noreferrer"&gt;sbt&lt;/a&gt; with Scala. If it doesn’t work for you for some reason, I can’t be much of a help here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See &lt;a href="https://mill-build.org/mill/0.11.11/Java_Intro_to_Mill.html" rel="noopener noreferrer"&gt;&lt;code&gt;mill&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;See other java build tools (like &lt;a href="https://maven.apache.org/" rel="noopener noreferrer"&gt;maven&lt;/a&gt;) or multi-language build tools (like &lt;a href="https://www.pantsbuild.org/" rel="noopener noreferrer"&gt;pants&lt;/a&gt; or &lt;a href="https://bazel.build/" rel="noopener noreferrer"&gt;bazel&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Miscellaneous
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;See &lt;a href="https://scala-cli.virtuslab.org/" rel="noopener noreferrer"&gt;Scala cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://docs.scala-lang.org/scala3/book/tools-worksheets.html" rel="noopener noreferrer"&gt;Scala worksheets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;See &lt;a href="https://scastie.scala-lang.org/" rel="noopener noreferrer"&gt;Scastie&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Searching for functions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;There’s nothing like hoogle.&lt;/strong&gt; The dot-completion and the go-to-definition for libraries often work. But, honestly, I regularly search through the github looking for functions (and instances). I don’t know what normal people do. &lt;/p&gt;

&lt;h3&gt;
  
  
  Searching for libraries
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Search in the organization/project lists. &lt;a href="https://zio.dev/ecosystem/" rel="noopener noreferrer"&gt;Example 1&lt;/a&gt; and &lt;a href="https://typelevel.org/projects/" rel="noopener noreferrer"&gt;Example 2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Search on &lt;a href="https://index.scala-lang.org/" rel="noopener noreferrer"&gt;scaladex&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Search on github.&lt;/li&gt;
&lt;li&gt;Ask a friend.&lt;/li&gt;
&lt;li&gt;Just use a java library.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Managing dependency versions
&lt;/h3&gt;

&lt;p&gt;There is no stackage. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some people use &lt;a href="https://github.com/tkawachi/sbt-lock" rel="noopener noreferrer"&gt;sbt-lock,&lt;/a&gt; &lt;a href="https://github.com/stringbean/sbt-dependency-lock" rel="noopener noreferrer"&gt;sbt-dependency-lock&lt;/a&gt; to get lock (freeze) files.&lt;/li&gt;
&lt;li&gt;Some people use &lt;a href="https://github.com/scala-steward-org/scala-steward" rel="noopener noreferrer"&gt;scala steward&lt;/a&gt;. A bot that helps keep dependencies up-to-date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can always fall back to checking the maven repository to see what are the dependencies. &lt;a href="https://mvnrepository.com/artifact/com.softwaremill.sttp.tapir/tapir-core" rel="noopener noreferrer"&gt;An example.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Books and other resources
&lt;/h2&gt;

&lt;p&gt;If you want to learn more, see &lt;a href="https://docs.scala-lang.org/" rel="noopener noreferrer"&gt;docs.scala-lang.org&lt;/a&gt;, &lt;a href="http://rockthejvm.com/" rel="noopener noreferrer"&gt;rockthejvm.com&lt;/a&gt;, and &lt;a href="https://www.youtube.com/watch?v=OdPaWmRnAc4&amp;amp;list=PLiYD0LWExCDkXGpYRY3WjNscDfhe4D0ND&amp;amp;ab_channel=fp-tower" rel="noopener noreferrer"&gt;Foundations of Functional Programming in Scala&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To Haskell devs, I used to recommend underscore’s books: &lt;a href="https://underscore.io/books/essential-scala/" rel="noopener noreferrer"&gt;Essential Scala&lt;/a&gt; (&lt;strong&gt;to learn Scala&lt;/strong&gt;) and &lt;a href="https://underscore.io/books/scala-with-cats/" rel="noopener noreferrer"&gt;Scala With Cats&lt;/a&gt; (&lt;strong&gt;to learn the FP side of Scala&lt;/strong&gt;), but those are for Scala 2. The classic &lt;a href="https://www.manning.com/books/functional-programming-in-scala-second-edition" rel="noopener noreferrer"&gt;Functional Programming in Scala&lt;/a&gt; has a second edition updated for Scala 3 — it’s great if you want a deep dive into &lt;strong&gt;the&lt;/strong&gt; &lt;strong&gt;FP side of Scala&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you want to get weekly Scala content, see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://scalatimes.com/" rel="noopener noreferrer"&gt;Scala Times&lt;/a&gt; newsletter.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://petr-zapletal.medium.com/" rel="noopener noreferrer"&gt;This week in Scala&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to chat, see &lt;a href="https://www.scala-lang.org/community/" rel="noopener noreferrer"&gt;scala-lang.org/community&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  OOP and variance
&lt;/h2&gt;

&lt;p&gt;When it comes to the OOP side of Scala, I think the most important one to get familiar with is &lt;a href="https://docs.scala-lang.org/scala3/book/types-variance.html" rel="noopener noreferrer"&gt;variance&lt;/a&gt;. You might think you won’t need it if you don’t use inheritance to mix lists of cats and dogs. However, you’ll still see those &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;-&lt;/code&gt; around and encounter related compilation errors. &lt;/p&gt;

&lt;p&gt;More and more libraries deal with this to make your life easier, so you might not even need to worry about it…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 If you are familiar with functors, depending on how well you’re familiar, it might help or hurt you to apply the knowledge of variance here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Few things you’ll need sooner or later
&lt;/h2&gt;

&lt;p&gt;You might encounter different sub-typing-related type relationships. See (upper and lower) &lt;a href="https://docs.scala-lang.org/tour/upper-type-bounds.html" rel="noopener noreferrer"&gt;type bounds&lt;/a&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;trait&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;+A&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nc"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepend&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&lt;/span&gt; &lt;span class="k"&gt;&amp;gt;:&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;B&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;NonEmptyList&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;B&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;If you encounter something that looks like &lt;em&gt;associated type&lt;/em&gt;, see &lt;a href="https://docs.scala-lang.org/tour/abstract-type-members.html" rel="noopener noreferrer"&gt;abstract type members&lt;/a&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;trait&lt;/span&gt; &lt;span class="nc"&gt;Buffer&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt;
  &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you encounter &lt;code&gt;*&lt;/code&gt;, see &lt;a href="https://docs.scala-lang.org/scala3/reference/changed-features/vararg-splices.html" rel="noopener noreferrer"&gt;varargs&lt;/a&gt; (for example, &lt;a href="https://www.scala-lang.org/api/current/scala/collection/immutable/List$.html#apply-2f" rel="noopener noreferrer"&gt;Array.apply()&lt;/a&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;val&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// in parameters&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;newL&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;*)&lt;/span&gt;        &lt;span class="c1"&gt;// splices in Scala 3  &lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;oldL&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="k"&gt;_&lt;/span&gt;&lt;span class="kt"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;// splices in Scala 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  End
&lt;/h3&gt;

&lt;p&gt;Congrats, you’re one step closer to mastering Scala. Just a few hundred more to go.&lt;/p&gt;




&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SpFs9rM1Mcg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>scala</category>
      <category>haskell</category>
      <category>functional</category>
    </item>
    <item>
      <title>Haskell for Scala developers</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Mon, 15 Jul 2024 02:53:18 +0000</pubDate>
      <link>https://forem.com/zelenya/haskell-for-scala-developers-2fg3</link>
      <guid>https://forem.com/zelenya/haskell-for-scala-developers-2fg3</guid>
      <description>&lt;p&gt;Imagine you’re my colleague: you have functional &lt;strong&gt;Scala experience&lt;/strong&gt; and must start contributing to the &lt;strong&gt;Haskell code&lt;/strong&gt;. These are the things I would share with you (over some period of time).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Context: subjective-&lt;strong&gt;production&lt;/strong&gt;-backend experience, web apps, microservices, shuffling jsons, and all that stuff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We will cover the main differences, similarities, major gotchas, and most useful resources. Consider this a rough map — just looking at this won’t make you a professional Haskell developer, but it should certainly save you (and the rest of the team) plenty of time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ I’ll use &lt;strong&gt;Haskell&lt;/strong&gt; and &lt;strong&gt;GHC&lt;/strong&gt; interchangeably, which is “technically” incorrect. But it’s 2024. Who cares.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;📹 Hate reading articles? Check out &lt;a href="https://youtu.be/SpFs9rM1Mcg" rel="noopener noreferrer"&gt;the complementary video&lt;/a&gt;, which covers the same content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic syntax and attitude
&lt;/h2&gt;

&lt;p&gt;You can (and should) pick up syntax by yourself, but here are the things you should conquer first:&lt;/p&gt;

&lt;h3&gt;
  
  
  Driving on the wrong side of the road
&lt;/h3&gt;

&lt;p&gt;You have to get used to reading chains of operations “in the opposite direction”. Take this Scala code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extractErrorMessage&lt;/span&gt;&lt;span class="nb"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asLeft&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;F&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are multiple ways to translate it into Haskell; the most straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;extractErrorMessage&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the order of &lt;strong&gt;functions&lt;/strong&gt; and the way we call &lt;strong&gt;functions&lt;/strong&gt; (e.g., no parentheses after &lt;code&gt;extractErrorMessage&lt;/code&gt;). We can avoid even more parentheses by the using function application operator (&lt;code&gt;f $ x&lt;/code&gt; is the same as &lt;code&gt;f x&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;extractErrorMessage&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can avoid the rest of the plumbing by using function composition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- read from right to left&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;extractErrorMessage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the wild, you will see all of these styles as well as their mix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function signatures
&lt;/h3&gt;

&lt;p&gt;Did you notice that Haskell’s functions had no type signatures?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Haskell is pretty good at inferring types. We can omit type signatures even in the top-level definitions. We can, but it doesn’t mean that we should!&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;extractErrorMessage&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type signature goes above the function definition. It might feel awkward to connect a name to a type, but among other things, it allows you to focus on types (while ignoring the names).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 The &lt;code&gt;undefined&lt;/code&gt; value is like a type-inference-friendlier cousin of &lt;code&gt;???&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Names don’t matter?
&lt;/h3&gt;

&lt;p&gt;The last thing I want to cover before we move on to more interesting things is about common function names and operators.&lt;/p&gt;

&lt;p&gt;For reasons, Haskell has a &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:map" rel="noopener noreferrer"&gt;&lt;code&gt;map&lt;/code&gt;&lt;/a&gt; function that only works on lists. Functor has &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:fmap" rel="noopener noreferrer"&gt;&lt;code&gt;fmap&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There’s no &lt;code&gt;flatMap&lt;/code&gt;, there is &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:-62--62--61-" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;&lt;/a&gt; (bind operator), and in general Haskell codebases (and developers) are usually more operator tolerable (some are too tolerable):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="kr"&gt;case&lt;/span&gt; 
  &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;
  &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;traverse&lt;/code&gt; is still &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:traverse" rel="noopener noreferrer"&gt;&lt;code&gt;traverse&lt;/code&gt;&lt;/a&gt;, and everything else you can pick up as you go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic concepts and fp
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Function composition and&lt;/strong&gt; Currying
&lt;/h3&gt;

&lt;p&gt;As I’ve mentioned in &lt;a href="https://youtu.be/K76vrOzU53o" rel="noopener noreferrer"&gt;the first Haskell vs. Scala video&lt;/a&gt;, in Haskell, function composition and currying are first-class citizens. Both are powerful enough to make the code tidier and more elegant, as well as the opposite. You certainly have to practice to get better at writing and reading.&lt;/p&gt;

&lt;p&gt;If you find some code confusing (or yourself wrote some code that the compiler doesn’t accept), try rewriting it: make it more verbose, introduce intermediate variables, and so on. It’s ok. It’s not a one-liner competition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt; 
    &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
    &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;defaultSubscription&lt;/span&gt;

    &lt;span class="n"&gt;userSubscription&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;Subscription&lt;/span&gt;
    &lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, if it feels like number of arguments is getting out of control, try introducing records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userInfo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;BundleServiceUrl&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Cache&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;UserInfo&lt;/span&gt;
&lt;span class="n"&gt;userInfo&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userInfo'&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;UserIds&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;UserInfo&lt;/span&gt;
&lt;span class="n"&gt;userInfo'&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserIds&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Purity
&lt;/h3&gt;

&lt;p&gt;When writing Haskell, you &lt;strong&gt;can not&lt;/strong&gt; just use a quick &lt;code&gt;var&lt;/code&gt; or a temporary &lt;code&gt;prinltn&lt;/code&gt;. Depending on your experience and workflows, it can be or not be a big deal. &lt;/p&gt;

&lt;p&gt;You might need to get used to it. You can start by getting familiar with &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Debug-Trace.html" rel="noopener noreferrer"&gt;Debug.Trace&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;userSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="n"&gt;withDiscount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;traceShowId&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: because of laziness, it might not be as trivial (a value might never be evaluated).&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 See &lt;a href="https://studio.youtube.com/video/iAzaShuVpPc/edit" rel="noopener noreferrer"&gt;Debugging without a “real” debugger&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Laziness
&lt;/h3&gt;

&lt;p&gt;Otherwise, I think you &lt;strong&gt;shouldn’t worry&lt;/strong&gt; about laziness at the beginning of your journey. Trust the compiler. If you’re too worried about performance and resources, keep an eye on the metrics.&lt;/p&gt;

&lt;p&gt;When needed, use existing code as a reference; for example, if you see exclamation points (&lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/strict.html#extension-BangPatterns" rel="noopener noreferrer"&gt;&lt;code&gt;BangPatterns&lt;/code&gt;&lt;/a&gt;) or a &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/strict.html" rel="noopener noreferrer"&gt;&lt;code&gt;StrictData&lt;/code&gt;&lt;/a&gt; extension where the data is defined, copy-paste first and ask questions later!&lt;/p&gt;

&lt;p&gt;Two great series on laziness in Haskell (you can find even more online):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=fSqE-HSh_NU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=fSqE-HSh_NU&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DSy7bscJL7k&amp;amp;t=0s&amp;amp;ab_channel=Serokell" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=DSy7bscJL7k&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Modules and Imports
&lt;/h3&gt;

&lt;p&gt;There are no classes and objects. &lt;/p&gt;

&lt;p&gt;You might quickly run into a problem with naming conflicts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Text&lt;/span&gt; &lt;span class="c1"&gt;-- (Text, strip)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.List&lt;/span&gt; 

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;
&lt;span class="c1"&gt;--    ^^^^^^&lt;/span&gt;
&lt;span class="c1"&gt;-- Ambiguous occurrence ‘filter’&lt;/span&gt;
&lt;span class="c1"&gt;-- It could refer to&lt;/span&gt;
&lt;span class="c1"&gt;--   either ‘Data.List.filter’&lt;/span&gt;
&lt;span class="c1"&gt;--       or ‘Data.Text.filter’&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to get into a habit of using qualified imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Text&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.Text&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.List&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt; &lt;span class="c1"&gt;-- stylistic choice&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some libraries suggest the users to qualify their imports, some people prefer to qualify &lt;strong&gt;all&lt;/strong&gt; their imports, but, at the end of the day, it’s a personal/team choice.&lt;/p&gt;

&lt;p&gt;📹 &lt;a href="https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString.html" rel="noopener noreferrer"&gt;bytestrings&lt;/a&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.HashMap.Strict&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;HashMap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.HashMap.Strict&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;HashMap&lt;/span&gt;
&lt;span class="c1"&gt;-- import qualified Data.HashMap.Strict as HM&lt;/span&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;HashMap&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Char&lt;/span&gt;
&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromList&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="c1"&gt;--         HM.fromList [(1, 'a'), (2, 'b')]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’d say, start using qualified imports for collections (containers) and strings (&lt;a href="https://hackage.haskell.org/package/text" rel="noopener noreferrer"&gt;texts&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString.html" rel="noopener noreferrer"&gt;bytestrings&lt;/a&gt;), and see how it goes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard library
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Standard library (std module) is called &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html" rel="noopener noreferrer"&gt;Prelude&lt;/a&gt;. It’s imported by default into all Haskell modules unless explicitly imported or disabled by the &lt;code&gt;NoImplicitPrelude&lt;/code&gt; extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You should pay attention when using Haskell’s standard library, (at least) for two reasons.&lt;/p&gt;

&lt;p&gt;It provides things that you &lt;strong&gt;shouldn’t use&lt;/strong&gt; in production; for example, &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Prelude.html#v:head" rel="noopener noreferrer"&gt;&lt;code&gt;head&lt;/code&gt;&lt;/a&gt; (that crashes a program on an empty list), &lt;code&gt;String&lt;/code&gt; (see &lt;a href="https://hackage.haskell.org/package/text" rel="noopener noreferrer"&gt;text /&lt;/a&gt; &lt;a href="https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString.html" rel="noopener noreferrer"&gt;bytestring&lt;/a&gt;), and lazy IO operations (see streaming libraries).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Also see the &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/overloaded_strings.html?highlight=overloaded%20strings#extension-OverloadedStrings" rel="noopener noreferrer"&gt;&lt;code&gt;OverloadedStrings&lt;/code&gt;&lt;/a&gt; extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It &lt;strong&gt;doesn’t provide&lt;/strong&gt; things you might expect or provides them in unexpected ways. For example, there is no &lt;code&gt;distinct&lt;/code&gt; to ignore duplicate elements from a list, but there is &lt;code&gt;nub&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distinct&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&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 haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nub&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- [1,2,3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no &lt;code&gt;contains&lt;/code&gt;, there is &lt;code&gt;elem&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="kt"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is commonly written using infix form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;code&gt;elem&lt;/code&gt; is not prefixed with &lt;code&gt;List&lt;/code&gt;, cause it comes from &lt;code&gt;Foldable&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And stuff like that. Be more open-minded (and careful).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🥈 Some companies use alternative preludes (existing or custom) not to deal with the standard prelude.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Product Types
&lt;/h3&gt;

&lt;p&gt;No easy way to put this. Records in Haskell can be irritating. You’ll find out really fast.&lt;/p&gt;

&lt;p&gt;It’s annoying when you use records with the same field names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;UserIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;UserIds&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;SubscriptionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;--                                        ^^^^^^^^^^^^^^&lt;/span&gt;
&lt;span class="c1"&gt;-- Multiple declarations of ‘subscriptionId’&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it’s annoying when you need to access or update nested records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*I’m not even going to illustrate this in vanilla Haskell.*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wouldn’t recommend using vanilla records. You have to get familiar with a couple of extensions. You can start with &lt;a href="https://downloads.haskell.org/~ghc/9.2.1/docs/html/users_guide/exts/overloaded_record_dot.html" rel="noopener noreferrer"&gt;&lt;code&gt;OverloadedRecordDot&lt;/code&gt;&lt;/a&gt; (since: GHC &lt;code&gt;9.2.0&lt;/code&gt;) and &lt;a href="https://downloads.haskell.org/~ghc/9.2.1/docs/html/users_guide/exts/duplicate_record_fields.html#extension-DuplicateRecordFields" rel="noopener noreferrer"&gt;&lt;code&gt;DuplicateRecordFields&lt;/code&gt;&lt;/a&gt;. Additionally: &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/field_selectors.html" rel="noopener noreferrer"&gt;&lt;code&gt;NoFieldSelectors&lt;/code&gt;&lt;/a&gt; (incl. in &lt;code&gt;GHC2021&lt;/code&gt;), &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/record_puns.html#extension-NamedFieldPuns" rel="noopener noreferrer"&gt;&lt;code&gt;NamedFieldPuns&lt;/code&gt;&lt;/a&gt; (incl. in &lt;code&gt;GHC2021&lt;/code&gt;), and maybe…maybe &lt;code&gt;RecordWildCards&lt;/code&gt;. Don’t expect a smooth ride.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 We cover &lt;code&gt;GHC2021&lt;/code&gt; in the extension section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s also common to use lenses via some optic library. There are quite a few options. Pick you poison: &lt;a href="https://hackage.haskell.org/package/lens" rel="noopener noreferrer"&gt;&lt;code&gt;lens&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/optics" rel="noopener noreferrer"&gt;&lt;code&gt;optics&lt;/code&gt;,&lt;/a&gt; &lt;a href="https://hackage.haskell.org/package/generic-lens" rel="noopener noreferrer"&gt;&lt;code&gt;generic-lens&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/lens-simple" rel="noopener noreferrer"&gt;&lt;code&gt;lens-simple&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/microlens" rel="noopener noreferrer"&gt;&lt;code&gt;microlens&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/profunctor-optics" rel="noopener noreferrer"&gt;&lt;code&gt;profunctor-optics&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/prolens" rel="noopener noreferrer"&gt;&lt;code&gt;prolens&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡  If you can’t afford &lt;code&gt;GHC 9.2.0&lt;/code&gt; (or higher) or lenses, you can also checkout &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/hasfield.html" rel="noopener noreferrer"&gt;&lt;code&gt;getField&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sum types
&lt;/h3&gt;

&lt;p&gt;It can be a bit unexpected, but Haskell allows partial field accessors (with a warning).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Role&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;internalId&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Admin&lt;/span&gt;

&lt;span class="n"&gt;dont&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;dont&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;internalId&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dont&lt;/span&gt; &lt;span class="kt"&gt;Admin&lt;/span&gt;
&lt;span class="c1"&gt;-- *** Exception: No match in record selector internalId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m mentioning this just in case. I’ve never cared or worried about this. Just use pattern matching like you would in Scala.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Polymorphism&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;What in the Java world is called generics, in the Haskell world is called parametric polymorphism.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- a is a type parameter&lt;/span&gt;
&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t want to go into details here, you shouldn’t see this that often, eventually, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/explicit_forall.html" rel="noopener noreferrer"&gt;Explicit universal quantification (forall)&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- this version is explicitly quantified&lt;/span&gt;
&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other than that, in general practice, it’s not that different, so let’s talk about &lt;strong&gt;ad-hoc polymorphism&lt;/strong&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Type classes
&lt;/h3&gt;

&lt;p&gt;Unlike Scala, Haskell has built-in type classes — there's (guaranteed to be) at most one instance of a type class per type. &lt;/p&gt;

&lt;p&gt;Good news: &lt;strong&gt;No need to worry about imports!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are other things you’ll have to worry about at some point, but don’t worry about them right now. You can start by declaring the type class instances next to the type class (in the same module) or next to the data. &lt;/p&gt;

&lt;p&gt;Sometimes, when you need a new (custom) instance, you can introduce a newtype:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- User is declared in some other module&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; 

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Arbitrary&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;arbitrary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
     &lt;span class="kt"&gt;Positive&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;arbitrary&lt;/span&gt;
     &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;InvalidUser&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes, you can add &lt;strong&gt;an orphan instance&lt;/strong&gt; and not use a newtype (it’s not encouraged, but still legal and sometimes unavoidable):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# OPTIONS_GHC -fno-warn-orphans #-}&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Arbitrary&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And remember that you can get a lot for free with deriving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deriving
&lt;/h3&gt;

&lt;p&gt;In Haskell, you can derive a lot (starting with &lt;code&gt;Show&lt;/code&gt;, all the way to &lt;code&gt;Traversable&lt;/code&gt; and beyond).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE GeneralizedNewtypeDeriving #-}&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;MyApp&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;MyApp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;unApp&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ReaderT&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Applicative&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Monad&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;MonadReader&lt;/span&gt; &lt;span class="kt"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usually, a library will have some examples of how to derive required type class instances, including imports and extensions. And if it doesn’t include the extensions (or you copied a code from somewhere else), the compiler will give you a hint.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson.html" rel="noopener noreferrer"&gt;aeson&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE DeriveGeneric #-}&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Aeson&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FromJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;GHC.Generics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;FromJSON&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To expand your vocabulary, start with &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/newtype_deriving.html" rel="noopener noreferrer"&gt;&lt;code&gt;GeneralizedNewtypeDeriving&lt;/code&gt;&lt;/a&gt;(incl. in &lt;code&gt;GHC2021&lt;/code&gt;). Then checkout &lt;strong&gt;strategies&lt;/strong&gt;, &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/deriving_strategies.html#extension-DerivingStrategies" rel="noopener noreferrer"&gt;&lt;code&gt;DerivingStrategies&lt;/code&gt;&lt;/a&gt; (incl. in &lt;code&gt;GHC2021&lt;/code&gt;), &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/deriving_via.html" rel="noopener noreferrer"&gt;&lt;code&gt;DerivingVia&lt;/code&gt;&lt;/a&gt;, and maybe &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/derive_any_class.html" rel="noopener noreferrer"&gt;&lt;code&gt;DeriveAnyClass&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- DerivingStrategies is implied by DerivingVia&lt;/span&gt;
&lt;span class="c1"&gt;-- {-# LANGUAGE DerivingStrategies #-}&lt;/span&gt;

&lt;span class="cp"&gt;{-# LANGUAGE DerivingVia #-}&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Aeson&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FromJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;getQuota&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Ord&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;FromJSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/deriving.html" rel="noopener noreferrer"&gt;The GHC docs&lt;/a&gt; are good. There are a couple of other guides online.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Meta Programming
&lt;/h2&gt;

&lt;p&gt;The two most common ways to generate boilerplate in Haskell are &lt;strong&gt;Template Haskell&lt;/strong&gt; (TH) and &lt;strong&gt;generic programming&lt;/strong&gt;. Not java generics. Even more generic generics!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 That’s one of the reasons not to refer to parametric polymorphism as just (java) generic types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Template Haskell&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s start with &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/template_haskell.html" rel="noopener noreferrer"&gt;Template Haskell&lt;/a&gt;, cause it’s easier to explain (&lt;em&gt;as an overview, I would claim that about the actual explanation&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;You use the &lt;code&gt;TemplateHaskell&lt;/code&gt; language extension and write template haskell or you use code that generates boilerplate via TH.&lt;/p&gt;

&lt;p&gt;Libraries often provide a specific TH module (or even a package) with functions to derive necessary instances. For example, &lt;a href="https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson-TH.html" rel="noopener noreferrer"&gt;Data.Aeson.TH&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE TemplateHaskell #-}&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Aeson.TH&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;deriveJSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deriveJSON&lt;/span&gt; &lt;span class="n"&gt;defaultOptions&lt;/span&gt; &lt;span class="n"&gt;''Product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Generic programming&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Generic programming comes in different shapes and forms. I’d say the most relevant is &lt;code&gt;GHC.Generics&lt;/code&gt; with the &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/generics.html#extension-DeriveGeneric" rel="noopener noreferrer"&gt;&lt;code&gt;DeriveGeneric&lt;/code&gt;&lt;/a&gt; extension (incl. in &lt;code&gt;GHC2021&lt;/code&gt;), because it’s the one that libraries usually use. Once again, let’s look at &lt;a href="https://hackage.haskell.org/package/aeson-2.2.3.0/docs/Data-Aeson.html" rel="noopener noreferrer"&gt;aeson&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cp"&gt;{-# LANGUAGE DeriveGeneric #-}&lt;/span&gt;

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Aeson&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;FromJSON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;GHC.Generics&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Generic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;ToJSON&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;FromJSON&lt;/span&gt; &lt;span class="kt"&gt;Product&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is also &lt;a href="https://hackage.haskell.org/package/generics-sop" rel="noopener noreferrer"&gt;&lt;code&gt;generics-sop&lt;/code&gt;&lt;/a&gt;, which is seemingly more accessible than &lt;code&gt;GHC.Generics&lt;/code&gt; if you want to generate your &lt;strong&gt;own&lt;/strong&gt; boilerplate (&lt;em&gt;maybe in the future; probably, if you’re watching this, you should not be writing generic code like that&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;There is also generic programming via &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Typeable.html" rel="noopener noreferrer"&gt;&lt;code&gt;Data.Typeable&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-Data.html" rel="noopener noreferrer"&gt;&lt;code&gt;Data.Data&lt;/code&gt;&lt;/a&gt; (see Scrap Your Boilerplate). It came before &lt;code&gt;GHC.Generics&lt;/code&gt;, uses a different approach, and feels more straightforward. However, it’s usually &lt;a href="https://hackage.haskell.org/package/aeson-0.7.0.4/docs/Data-Aeson-Generic.html" rel="noopener noreferrer"&gt;not recommended&lt;/a&gt; any more because it’s less efficient. &lt;em&gt;That’s what they say on the internets. I’ve never compared any of those.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;🌯 So, Template Haskell is like macros, generics are like shapeless.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;As I’ve mentioned in the overview, there is no consensus on writing Haskell. Whatsoever. On any topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstractions and type classes
&lt;/h3&gt;

&lt;p&gt;However, it’s essential to know your type classes. Those are a must: &lt;code&gt;Functor&lt;/code&gt;, &lt;code&gt;Applicative&lt;/code&gt;, &lt;code&gt;Monad&lt;/code&gt;, &lt;code&gt;Semigroup&lt;/code&gt;, &lt;code&gt;Monoid&lt;/code&gt;, &lt;code&gt;Foldable&lt;/code&gt;, &lt;code&gt;Traversable&lt;/code&gt;, and &lt;code&gt;Alternative&lt;/code&gt;. If the library has a functionality that can be provided by one of those (&lt;em&gt;e.g., smooshing or mapping things&lt;/em&gt;), it’s likely that it’s going to be provided and won’t be very documented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Failure handling
&lt;/h3&gt;

&lt;p&gt;The situation is not much better than in Scala. &lt;em&gt;I can’t help you here, you’re on your own.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Option&lt;/code&gt; is called &lt;code&gt;Maybe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;Exception&lt;/code&gt; and &lt;code&gt;SomeExceptions&lt;/code&gt; (cousins of &lt;code&gt;Throwable&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;See synchronous exceptions (throwing exceptions in &lt;code&gt;IO&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;safe-exceptions&lt;/code&gt; package (throwing exceptions in &lt;code&gt;~~F[_]~~&lt;/code&gt;, &lt;em&gt;I mean &lt;code&gt;MonadThrow m =&amp;gt; m a&lt;/code&gt;&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Maybe see &lt;a href="https://hackage.haskell.org/package/unliftio-0.2.25.0/docs/UnliftIO-Exception.html" rel="noopener noreferrer"&gt;&lt;code&gt;UnliftIO.Exception&lt;/code&gt;&lt;/a&gt; as a &lt;code&gt;safe-exceptions&lt;/code&gt; surrogate.&lt;/li&gt;
&lt;li&gt;See asynchronous exceptions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You might be tempted to use &lt;code&gt;error "this should never happen"&lt;/code&gt; in “pure” code — just a friendly reminder it eventually &lt;strong&gt;does happen&lt;/strong&gt;. Don’t be lazy, don’t trust other teams to respect your contracts, and be cautious. Think about your future self.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styles and flavors
&lt;/h3&gt;

&lt;p&gt;From time to time, people bring up Simple Haskell, Boring Haskell, and stuff like that. But there are no actual rules, communities, or many guidelines for those.&lt;/p&gt;

&lt;p&gt;The one way that Haskell (GHC) varies between companies and projects is via the language extensions. You need to start recognising extensions and what they change: notice which extensions are enabled per module and which for the whole project (or package). Also get familiar with &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html#controlling-editions-and-extensions" rel="noopener noreferrer"&gt;language editions&lt;/a&gt; — such as &lt;code&gt;GHC2021&lt;/code&gt; and &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/control.html#extension-GHC2024" rel="noopener noreferrer"&gt;&lt;code&gt;GHC2024&lt;/code&gt;&lt;/a&gt; — how to enable those and what’s included.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organizing code
&lt;/h3&gt;

&lt;p&gt;There is plain IO, mtl and transformers, custom monads (on top of those), IO + Reader(T), RIO, &lt;a href="https://github.com/fpco/unliftio" rel="noopener noreferrer"&gt;unliftio&lt;/a&gt;, services and &lt;a href="https://jaspervdj.be/posts/2018-03-08-handle-pattern.html" rel="noopener noreferrer"&gt;handle&lt;/a&gt; patterns, free monads, &lt;a href="https://hackage.haskell.org/package/freer-simple" rel="noopener noreferrer"&gt;freer-simple&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/extensible-effects" rel="noopener noreferrer"&gt;extensible-effects&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/fused-effects" rel="noopener noreferrer"&gt;fused-effects&lt;/a&gt;, &lt;a href="https://github.com/hasura/eff" rel="noopener noreferrer"&gt;eff&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/effectful" rel="noopener noreferrer"&gt;effectful&lt;/a&gt;, &lt;a href="https://hackage.haskell.org/package/cleff" rel="noopener noreferrer"&gt;cleff&lt;/a&gt;, &lt;a href="https://github.com/polysemy-research/polysemy" rel="noopener noreferrer"&gt;polysemy&lt;/a&gt;, &lt;a href="https://github.com/tomjaguarpaw/bluefin" rel="noopener noreferrer"&gt;bluefin&lt;/a&gt;, and other effect libraries (&lt;em&gt;that I forgot to mention&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;I could oversimplify and say, if you used cats-effect and tagless final use &lt;em&gt;THIS&lt;/em&gt;, or if you used ZIO use &lt;em&gt;THAT&lt;/em&gt;, but what’s the fun in that? &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 A quick note: if you’re looking for something like &lt;code&gt;Resource&lt;/code&gt; (for your library of choice) and can’t find it or make it work, try starting or searching from &lt;code&gt;bracket&lt;/code&gt; and functions prefixed with &lt;code&gt;with&lt;/code&gt; (e.g., &lt;code&gt;withPool&lt;/code&gt;). Also, see &lt;a href="https://hackage.haskell.org/package/resourcet" rel="noopener noreferrer"&gt;resourcet&lt;/a&gt; and &lt;a href="https://hackage.haskell.org/package/managed" rel="noopener noreferrer"&gt;managed&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Runtime and concurrency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Green threads (provided by Haskell runtime system).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MVar&lt;/code&gt; is &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Control-Concurrent-MVar.html" rel="noopener noreferrer"&gt;&lt;code&gt;MVar&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;Ref&lt;/code&gt; is &lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-IORef.html" rel="noopener noreferrer"&gt;&lt;code&gt;IORef&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;async&lt;/code&gt; package.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;STM&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;See &lt;code&gt;bracket&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📕 Bonus: See Parallel and Concurrent Programming in Haskell by Simon Marlow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;📹 Okay, okay, let’s go back to stuff I can actually be a bit of help.&lt;/p&gt;

&lt;p&gt;There’s no universal answer when it comes to tooling. If you’re using nix, do what you're doing. If not — install &lt;a href="https://www.haskell.org/ghcup/" rel="noopener noreferrer"&gt;ghcup&lt;/a&gt; and install everything else through it (it’s kind of like &lt;code&gt;cs setup&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;There are two main build tools in Haskell: &lt;a href="https://cabal.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Cabal&lt;/a&gt; and &lt;a href="https://docs.haskellstack.org/en/stable/" rel="noopener noreferrer"&gt;Stack&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the team or project that you’re using uses one — choose that one.&lt;/li&gt;
&lt;li&gt;If you’re starting a new project for yourself — you can choose by throwing a coin (or &lt;em&gt;partially&lt;/em&gt; depending on the preferred dependency workflow; &lt;em&gt;see below&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Editor
&lt;/h3&gt;

&lt;p&gt;You can use ghcup to install &lt;strong&gt;HLS&lt;/strong&gt; (Haskell Language Server) – Haskell LSP support, so you can use whatever supports LSP.&lt;/p&gt;

&lt;p&gt;I use vs code. Using Haskell with it is not that different from using Scala. You can also use IntelliJ via &lt;a href="https://plugins.jetbrains.com/plugin/24123-haskell-lsp" rel="noopener noreferrer"&gt;the LSP plugin&lt;/a&gt; — obviously don’t expect java-level IDE support.&lt;/p&gt;

&lt;h3&gt;
  
  
  REPL / GHCI
&lt;/h3&gt;

&lt;p&gt;Try integrating &lt;a href="https://downloads.haskell.org/ghc/latest/docs/users_guide/ghci.html" rel="noopener noreferrer"&gt;ghci&lt;/a&gt; into your development workflow. It’s more than just a repl — it’s closer to Scala worksheets with abilities to debug and inspect; for example, get a type or a kind of expression and get available (type-class) instances for a data type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤷 In other words, if there is some Scala/IntelliJ functionality/workflow that is missing in the Haskell editor, you might substitute it by using GHCi.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Searching for functions
&lt;/h3&gt;

&lt;p&gt;If you’re looking for some function or some data type, you can still use dot completion on a module, but if you don’t know where to look, try &lt;a href="https://hoogle.haskell.org/" rel="noopener noreferrer"&gt;hoogle&lt;/a&gt; (or local alternative).&lt;/p&gt;

&lt;p&gt;You can also use typed holes, to get compiler suggestions (it also works in the editor).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="n"&gt;someUserId&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;• Found hole: _ :: UserId -&amp;gt; IO (Either a0 User)
  Where: ‘a0’ is an ambiguous type variable
• In the first argument of ‘(&amp;gt;&amp;gt;=)’, namely ‘_ someUserId’
  In the expression ...
• Relevant bindings include
    ...
  Valid hole fits include fetchUser
  Valid refinement hole fits include
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Searching for libraries
&lt;/h3&gt;

&lt;p&gt;If you’re looking for a library (a package), you can still poke around hoogle or search &lt;a href="https://hackage.haskell.org/packages/browse" rel="noopener noreferrer"&gt;hackage&lt;/a&gt; (central package archive) by tags.&lt;/p&gt;

&lt;p&gt;But here is the first catch: there could be &lt;strong&gt;too many options&lt;/strong&gt;. For example, see my video on Haskell and Postgres. &lt;em&gt;I don’t have a rule of thumb here.&lt;/em&gt; You can try asking around, but the more people you ask — the more answers you get. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 Maybe the solution is to ask only one person or two, not more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The opposite is also common, sometimes &lt;strong&gt;there are no options&lt;/strong&gt;. Sometimes there are bindings on top of a C library. &lt;a href="https://hackage.haskell.org/package/hw-kafka-client" rel="noopener noreferrer"&gt;For example&lt;/a&gt;. So, if you can’t find anything, there is always C FFI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching for dependency versions
&lt;/h3&gt;

&lt;p&gt;You don’t have to search for (or use) specific library versions compatible with other libraries. &lt;/p&gt;

&lt;p&gt;There are a few other ways to deal with dependency versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing dependency versions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You can use stackage snapshots (snapshot is a set of compatible Haskell libraries).&lt;/li&gt;
&lt;li&gt;You can use loose version bounds or no bounds at all for your dependencies (if you don’t care about reproducibility or like living on the edge).&lt;/li&gt;
&lt;li&gt;You can use &lt;a href="https://cabal.readthedocs.io/en/stable/nix-local-build.html#how-can-i-have-a-reproducible-set-of-versions-for-my-dependencies" rel="noopener noreferrer"&gt;&lt;code&gt;cabal freeze&lt;/code&gt;&lt;/a&gt; to pin down the dependencies, which ensures (more) reproducible builds. Something like &lt;a href="https://github.com/tkawachi/sbt-lock" rel="noopener noreferrer"&gt;sbt-lock,&lt;/a&gt; &lt;a href="https://github.com/stringbean/sbt-dependency-lock" rel="noopener noreferrer"&gt;sbt-dependency-lock&lt;/a&gt;, or locks in other language ecosystems.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Books and other resources
&lt;/h2&gt;

&lt;p&gt;If you want to learn more, &lt;a href="https://www.haskell.org/documentation/" rel="noopener noreferrer"&gt;haskell.org&lt;/a&gt; has a list of all sorts of learning resources.&lt;/p&gt;

&lt;p&gt;If you want to get weekly Haskell content, see &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://haskellweekly.news/" rel="noopener noreferrer"&gt;https://haskellweekly.news/&lt;/a&gt; (newsletter)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://haskell.libhunt.com/" rel="noopener noreferrer"&gt;https://haskell.libhunt.com/&lt;/a&gt; (newsletter)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://haskell.pl-a.net/" rel="noopener noreferrer"&gt;https://haskell.pl-a.net/&lt;/a&gt; (aggregator)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to chat, see &lt;a href="https://discourse.haskell.org/" rel="noopener noreferrer"&gt;https://discourse.haskell.org/&lt;/a&gt;. Or find your own echo chamber.&lt;/p&gt;

&lt;h2&gt;
  
  
  Few things you’ll need sooner or later
&lt;/h2&gt;

&lt;p&gt;The last thing we cover. If you aren’t proactive enough with catching up with less-beginner Haskell, you might bump into unknown syntax. A few more pointers:&lt;/p&gt;

&lt;p&gt;If you encounter &lt;code&gt;@&lt;/code&gt; followed by a type, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_applications.html?highlight=type%20applications#extension-TypeApplications" rel="noopener noreferrer"&gt;&lt;code&gt;TypeApplications&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you encounter &lt;code&gt;|&lt;/code&gt; in a type class declaration, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/functional_dependencies.html" rel="noopener noreferrer"&gt;functional dependencies&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Monad&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;MonadState&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you encounter &lt;code&gt;type family&lt;/code&gt;, &lt;code&gt;data family&lt;/code&gt;, or an associated &lt;code&gt;type&lt;/code&gt; (or &lt;code&gt;data&lt;/code&gt;), see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_families.html" rel="noopener noreferrer"&gt;type families&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- something like this&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="n"&gt;family&lt;/span&gt; &lt;span class="kt"&gt;IsChar&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Foo&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="c1"&gt;-- or something like this&lt;/span&gt;
  &lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Bar&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Type&lt;/span&gt;
  &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bar&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you encounter too many &lt;code&gt;forall&lt;/code&gt;s or suspiciously nested &lt;code&gt;forall&lt;/code&gt;s, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/rank_polymorphism.html#extension-RankNTypes" rel="noopener noreferrer"&gt;&lt;code&gt;RankNTypes&lt;/code&gt;&lt;/a&gt; (or maybe &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/existential_quantification.html#extension-ExistentialQuantification" rel="noopener noreferrer"&gt;&lt;code&gt;ExistentialQuantification&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you feel like there is too much happening on the type level, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/data_kinds.html#extension-DataKinds" rel="noopener noreferrer"&gt;&lt;code&gt;DataKinds&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/type_literals.html#type-level-literals" rel="noopener noreferrer"&gt;Type-Level Literals&lt;/a&gt;, or something along those lines.&lt;/p&gt;

&lt;p&gt;If you see &lt;code&gt;where&lt;/code&gt; in a data declaration, see &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/gadt_syntax.html#extension-GADTSyntax" rel="noopener noreferrer"&gt;&lt;code&gt;GADTs&lt;/code&gt;&lt;/a&gt; (or &lt;a href="https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/gadt_syntax.html#extension-GADTSyntax" rel="noopener noreferrer"&gt;&lt;code&gt;GADTSyntax&lt;/code&gt;&lt;/a&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data Option a where
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  End
&lt;/h2&gt;

&lt;p&gt;Congrats, you’re one step closer to mastering Haskell. Just a few hundred more to go.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🌱  Hopefully this is useful as a standalone resource (even if you can’t ask follow-up questions).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SpFs9rM1Mcg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>scala</category>
      <category>functional</category>
    </item>
    <item>
      <title>What Scala does better than Haskell and vice versa</title>
      <dc:creator>Zelenya</dc:creator>
      <pubDate>Tue, 25 Jun 2024 04:04:00 +0000</pubDate>
      <link>https://forem.com/zelenya/what-scala-does-better-than-haskell-and-vice-versa-al6</link>
      <guid>https://forem.com/zelenya/what-scala-does-better-than-haskell-and-vice-versa-al6</guid>
      <description>&lt;p&gt;📹 Hate reading articles? Check out &lt;a href="https://youtu.be/K76vrOzU53o" rel="noopener noreferrer"&gt;the complementary video&lt;/a&gt;, which covers the same content.&lt;/p&gt;




&lt;p&gt;There is this meme that &lt;em&gt;Haskell is better than Scala&lt;/em&gt; or that &lt;em&gt;Scala is just a gateway drug to Haskell&lt;/em&gt;. A long time ago, I used to believe this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I saw how 4 different companies use Scala.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I saw how 4 different companies use Haskell&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After years of using both in multiple companies and meeting people who “went back to Scala”, it’s kind of sad to see people bring up these stereotypes repeatedly. Sure, the Haskell language influenced and inspired Scala, but there are so many things that I miss from Scala when I use Haskell… as well as vice versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ Disclaimer
&lt;/h2&gt;

&lt;p&gt;When talking about Scala or Haskell here — it’s not just about the languages themselves, but also about standard libraries and overall ecosystems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“All happy families are alike; each production is unhappy in its own way.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We’ll be talking from subjective-production-backend experience — from somebody dealing with web apps, microservices, shuffling jsons, and all that stuff. The emphasis is on the &lt;strong&gt;production&lt;/strong&gt; setting (not academic, theoretical, or blog post).&lt;/p&gt;

&lt;p&gt;For example, Scala is built on top of Java and has &lt;code&gt;null&lt;/code&gt;s, oh no! While in a day-to-day code, I  rarely encounter it. The last time I saw a &lt;code&gt;NullPointerException&lt;/code&gt; was more than 8 months ago. Not even in the Scala code. It was in the http response body — the vendor’s API returned internal errors in case of malformed input 🤷 (they used Spring).&lt;/p&gt;

&lt;p&gt;With this in mind…&lt;/p&gt;

&lt;h2&gt;
  
  
  FP dial
&lt;/h2&gt;

&lt;p&gt;One of the biggest things that separates Scala from Haskell is the ability to choose the level of FP or level of purity.&lt;/p&gt;

&lt;p&gt;I know how to use trace (and friends) to debug in Haskell, but it’s pretty convenient to sneak in an occasional &lt;code&gt;println&lt;/code&gt; anywhere I want.&lt;/p&gt;

&lt;p&gt;And I’m happy to admit, that I used a couple of mutable variables a few of months ago and it was great. I was migrating some convoluted functionality from legacy Ruby to Scala, and it was simpler to translate the core almost as is (in a non-fp way), add tests, remove unnecessary code, fix some edge cases, and only after rewrite in a functional style with a little &lt;code&gt;State&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Sure, it wouldn’t be the end of the world to rewrite that in Haskell as well — instead of intermediate representation, I would have to plan on paper or something…&lt;/p&gt;

&lt;p&gt;Fp-dial is also great for learning/teaching, occasional straightforward performance tweaks, and so on…&lt;/p&gt;

&lt;h2&gt;
  
  
  Laziness
&lt;/h2&gt;

&lt;p&gt;Another big difference is &lt;strong&gt;laziness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When writing Haskell, laziness allows us not to think or worry about stuff like stack safety; for example, we don’t have to worry about &lt;code&gt;*&amp;gt;&lt;/code&gt; vs &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;, we can look at the code of any Monad and it’s going to be just two functions — no &lt;code&gt;tailRecM&lt;/code&gt; or other tricks… &lt;em&gt;(it still doesn’t mean it’s going to be easy to read though)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And laziness gives more room for the compiler to be free and optimize whatever it wants.&lt;/p&gt;

&lt;p&gt;On the other hand, when writing Scala, it’s pretty nice not to worry about &lt;strong&gt;laziness&lt;/strong&gt;. Like I’ve mentioned before, I can &lt;code&gt;println&lt;/code&gt; (or see in the debugger) pretty much any variable and know that I will see it (and it will be evaluated). On top of that, no worrying about accumulating the thunks…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;😉 Don’t worry, there are other ways to leak memory on JVM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Function Composition and Currying
&lt;/h2&gt;

&lt;p&gt;Probably the biggest stylistic thing I miss from Haskell is &lt;strong&gt;function composition&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Starting with a concise composition operator (&lt;code&gt;.&lt;/code&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;extractErrorMessage&lt;/span&gt; &lt;span class="c1"&gt;-- Note: read from right to left&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Sure, it requires getting used to, some people abuse it, and so on. But function composition can be so elegant!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;optionalRawString&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What also helps Haskell’s elegance is currying — Haskell functions are curried, which makes function composition and reuse even more seamless:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enrichUserInfo&lt;/span&gt; &lt;span class="n"&gt;paymentInfo&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;extractUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;listOfEntities&lt;/span&gt;

&lt;span class="n"&gt;enrichUserInfo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;PaymentInfo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;UserInfo&lt;/span&gt;

&lt;span class="n"&gt;extractUser&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Entry&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At the same time, not having currying by default is to Scala’s advantage — it can notably improve error messages (which is also more beginner-friendly). When you miss an argument, the compiler tells you if you passed a &lt;code&gt;wrong number of parameters&lt;/code&gt; or which exact parameter is wrong:&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;enrichUserInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentInfo&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;PaymentInfo&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;IO&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;UserInfo&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;

&lt;span class="nf"&gt;enrichUserInfo&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="c1"&gt;// Found: User&lt;/span&gt;
&lt;span class="c1"&gt;// Required: PaymentInfo&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;

&lt;span class="nf"&gt;enrichUserInfo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentInfo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// missing argument for parameter user ...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Where clause
&lt;/h2&gt;

&lt;p&gt;Another style- or formatting-related thing that I really miss in Scala is having the ability to write things in the &lt;code&gt;where&lt;/code&gt; clauses.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;putStrLn&lt;/span&gt; &lt;span class="s"&gt;"Some other logic"&lt;/span&gt;
  &lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enrichUserInfo&lt;/span&gt; &lt;span class="n"&gt;paymentInfo&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;extractUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;listOfEntities&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;enrichUserInfo&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;PaymentInfo&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;UserInfo&lt;/span&gt;
    &lt;span class="n"&gt;enrichUserInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;

    &lt;span class="n"&gt;extractUser&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Entry&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
    &lt;span class="n"&gt;extractUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;undefined&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It’s not the same as declaring variables (before using them) and not the same as using private or nested functions. I like to have primary logic first and secondary — after (below) and be explicit that functions aren’t used anywhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types
&lt;/h2&gt;

&lt;p&gt;Let’s talk types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Newtypes and Sum types
&lt;/h3&gt;

&lt;p&gt;It feels like Haskell encourages us to make custom types, because of how uncluttered it is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Role&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="kt"&gt;Admin&lt;/span&gt; &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Eq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;&lt;span class="p"&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 haskell"&gt;&lt;code&gt;

&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Num&lt;/span&gt;

&lt;span class="n"&gt;remainingQuota&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Quota&lt;/span&gt;
&lt;span class="n"&gt;remainingQuota&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It’s just so neat and ergonomic! When I’m writing Scala, I might think about making a custom type but then give up and keep using &lt;code&gt;String&lt;/code&gt;s and &lt;code&gt;Boolean&lt;/code&gt;s…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🙏 Sure. One can use a library. Sure. It’s better with Scala 3. Still…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Product Types
&lt;/h3&gt;

&lt;p&gt;Funnily enough, Scala is way better at product types (records/case classes):&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;case&lt;/span&gt; &lt;span class="k"&gt;class&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;name&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="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Peach"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;name&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We don’t need to go into more details. If you have used Haskell, &lt;strong&gt;you know&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🙏 Sure. One can use lenses. Sure. It’s better with the latest extensions. Still…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Union Types
&lt;/h3&gt;

&lt;p&gt;On a related note, Scala 3 introduced union types:&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;customer&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;NotFound&lt;/span&gt; &lt;span class="kt"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;MissingScope&lt;/span&gt; &lt;span class="kt"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;DBisDead&lt;/span&gt;, &lt;span class="kt"&gt;CustomerId&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="n"&gt;customer&lt;/span&gt; &lt;span class="k"&gt;match&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Right&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;        &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;as200&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NotFound&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;  &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MissingScope&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;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;unauthorized&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nc"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DBisDead&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="nv"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Some useful information, {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;getErrorMessage&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;internalServerError&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Some nice message"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, introducing new error types doesn’t feel like a chore — we don’t need to build hierarchies or convert between different ones. I miss those in Haskell and Scala 2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🤔 The type could be even &lt;code&gt;CustomerId | NotFound | MissingScope | DBisDead&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Type inference
&lt;/h2&gt;

&lt;p&gt;Let’s keep it short: Haskell has great type inference. It works when you need it — I never feel like I have to help the compiler to do its job&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🙏 Not talking about more complicated type-level stuff — just normal fp code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, we can compose monad transformers without annotating a single one (or even the last one):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;program&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runExceptT&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;ExceptT&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;liftIO&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;findSubscription&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;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="kt"&gt;Subscription&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And when we use the wrong thing, the compiler has our back:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="n"&gt;program&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runExceptT&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;fetchUser&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;
  &lt;span class="n"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;liftIO&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;findSubscription&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&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 plaintext"&gt;&lt;code&gt;

• Found hole: _ :: IO (Either Error User) -&amp;gt; ExceptT Error IO User
• ...
  Valid hole fits include
    ExceptT :: forall e (m :: * -&amp;gt; *) a. m (Either e a) -&amp;gt; ExceptT e m a
      with ExceptT @Error @IO @User
      (imported from ‘Control.Monad.Except’ ...
        (and originally defined in transformers


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Modules and dot completion
&lt;/h2&gt;

&lt;p&gt;On the other side of the coin, Scala has a great module system — we can design composable programs, don’t worry about things like naming conflicts, and also… look what we can do:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdde0l2epi9omhi3c8mw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdde0l2epi9omhi3c8mw.png" alt="dot completion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;dot completion…&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hoogle
&lt;/h2&gt;

&lt;p&gt;To be fair, the dot-completion is good and all, and occasionally I miss it in Haskell. It’s, however, only useful when I already have a specific object or already know where to look. When we just start using the library, have a generic problem, or don’t even know what library to use yet; then the dot-completion won’t help us — but Haskell’s &lt;a href="https://hoogle.haskell.org/?hoogle=(a%20-%3E%20Bool)%20-%3E%20%5Ba%5D%20-%3E%20%5Ba%5D" rel="noopener noreferrer"&gt;hoogle&lt;/a&gt; is.&lt;/p&gt;

&lt;p&gt;We can search for generic things:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvnv2iodlbkkdp3fr3ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnvnv2iodlbkkdp3fr3ik.png" alt="Hoogle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And for more specific things, for example, we have an &lt;code&gt;ExceptT&lt;/code&gt;, how can we use it?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;

&lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ExceptT&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37k3wyh58dc6l37tb45g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F37k3wyh58dc6l37tb45g.png" alt="Hoogle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;If we look at the bigger picture, Scala has a better library situation — when I need to pick a library to solve some things, it’s usually easier to do in Scala.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🙏 Keep in mind the context. I know, for instance, Scala has nothing that comes close to Haskell’s parser libraries, but this is not what we’re talking about right now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's most notable in companies where many other teams use different stacks; we have to keep up with them (new serialization formats, new monitoring systems, new aws services, and so on).&lt;br&gt;
We rarely have to start from scratch in Scala because, at least, we can access the sea of java libraries.&lt;/p&gt;

&lt;p&gt;The opposite issue — when there are too many libraries for the same use-case — is just a bit less common in Scala. Mostly, when there are multiple libraries, it’s because each exists for a different Scala flavor (we’ll talk about this soon), but it’s often fine because it’s easy to pick one based on your style (&lt;em&gt;maybe not as easy for beginners 🤷&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;And then Scala libraries themselves are usually more production-ready and polished. Essentially, there are more Scala developers and more Scala in production, so the libraries go through more iterations and testing.&lt;/p&gt;
&lt;h3&gt;
  
  
  Library versions / Stackage
&lt;/h3&gt;

&lt;p&gt;However, when it comes to picking &lt;strong&gt;versions&lt;/strong&gt; of the libraries I prefer Haskell because it has Stackage — a community project, which maintains sets or snapshots of compatible Haskell libraries.&lt;/p&gt;

&lt;p&gt;We don’t need to brute-force which library versions are compatible or go through bunch of github readmes or release notes. The tools can pick the versions for us: either &lt;strong&gt;explicitly&lt;/strong&gt;, if we choose a specific resolver/snapshot (for example, &lt;a href="https://www.stackage.org/lts-22.25" rel="noopener noreferrer"&gt;lts-22.25&lt;/a&gt;); or &lt;strong&gt;implicitly&lt;/strong&gt;, by using loose version bounds (&lt;code&gt;base &amp;gt;= 4.7 &amp;amp;&amp;amp; &amp;lt; 5&lt;/code&gt;) and relying on the fact that Stackage incentivizes libraries to stay up-to-date and be compatible with others (or something like that).&lt;/p&gt;
&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;As I mentioned, there are various flavors of Scala (some say &lt;em&gt;different stacks&lt;/em&gt;): java-like Scala, python-like Scala, actor-based Scala, … &lt;em&gt;many others&lt;/em&gt;, and two fp Scalas: typelevel/cats-based and zio-based. Most of the time, they come with their core set of libraries and &lt;strong&gt;best practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s easy to get onboarded at a new code base or a company — no need to bike-shade every time about basic things like resource management or error handling. Of course, there are hype cycles and new whistles every few years, but Scala communities usually settle on a few things and move on.&lt;/p&gt;

&lt;p&gt;On the other hand, there is &lt;strong&gt;no consensus&lt;/strong&gt; on writing Haskell. Whatsoever. On any topic. And I’m going to contradict what I’ve just said, but I like it too — it can be really fun and rewarding as well. I have seen 4 production usages of Haskell: each company used a different effect system or ways to structure programs (&lt;em&gt;actually, half of them used even multiple different ones inside the same company&lt;/em&gt;), and it was enjoyable to learn, experiment, and compare.&lt;/p&gt;
&lt;h3&gt;
  
  
  Abstractions
&lt;/h3&gt;

&lt;p&gt;In a nutshell, all those (Scala/Haskell) effect systems are just monads with different boilerplate — if you used one, you used them all. It’s not a big deal to switch between them. &lt;/p&gt;

&lt;p&gt;And it’s another great thing about Haskell — the use or reuse of &lt;strong&gt;abstractions&lt;/strong&gt; and &lt;strong&gt;type classes&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;It’s typical for libraries to provide instances for common type classes. For example, if there is something to “combine”, there are probably semigroup and/or monoid instances. So, when Haskell developers pick up a new library, they already have some intuition on how to use it even without much documentation (&lt;em&gt;maybe not as easy for beginners 🤷&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Take, for instance, the &lt;a href="https://hackage.haskell.org/package/megaparsec-9.6.1/docs/Text-Megaparsec.html" rel="noopener noreferrer"&gt;Megaparsec&lt;/a&gt; parser library — most of the combinators are based on type classes; for example, we can use applicative’s pure to make a parser that succeeds without consuming input, alternative’s &lt;code&gt;&amp;lt;|&amp;gt;&lt;/code&gt; that implements &lt;a href="https://hackage.haskell.org/package/parser-combinators-1.3.0/docs/Control-Monad-Combinators.html#v:-60--124--62-" rel="noopener noreferrer"&gt;choice&lt;/a&gt;, and so on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Blitz round
&lt;/h2&gt;

&lt;p&gt;Let’s quickly cover a few other topics. We won’t give them too much time, because they are even more nuanced or niched (&lt;em&gt;or I was too lazy to come up with good examples&lt;/em&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Documentation, books, and other resources
&lt;/h3&gt;

&lt;p&gt;Speaking of documentation, originally, when I sketched out this guide, I was going to say that Scala is better at teaching (documentation, books, courses, and whatever), but after sleeping on it (more than a couple nights), I don’t think it’s the case — I don’t think one is doing strictly better than the other on this front (&lt;em&gt;as of 2024&lt;/em&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  Type classes
&lt;/h3&gt;

&lt;p&gt;Probably the first and the most common topic people bring up when comparing Scala to Haskell is type classes: in Haskell, there's (guaranteed to be) one instance of a type class per type (Scala allows multiple implicit instances of a type).&lt;/p&gt;

&lt;p&gt;There are a lot of good properties as a consequence, but honestly, the best one is that there is no need to remember what to import to get instances.&lt;/p&gt;
&lt;h3&gt;
  
  
  Type-level programming
&lt;/h3&gt;

&lt;p&gt;If you like it when your language allows you to do “a lot” of type-level programming, it’s an extra point for Haskell.&lt;/p&gt;

&lt;p&gt;If you don’t like it when your colleagues spend too much time playing on the type-level or don’t like complex error messages, it’s an extra point for Scala.&lt;/p&gt;
&lt;h3&gt;
  
  
  Build times
&lt;/h3&gt;

&lt;p&gt;Scala compiles faster.&lt;/p&gt;
&lt;h3&gt;
  
  
  Runtime and concurrency
&lt;/h3&gt;

&lt;p&gt;I think, in theory, Haskell has a strong position here: green thread, STM, and other great concurrency primitives. &lt;/p&gt;

&lt;p&gt;However, in practice, I prefer writing concurrent code in Scala. Maybe it’s because I’m scared of Haskell’s interruptions and async exceptions, maybe it’s because occasionally I can just replace &lt;code&gt;map&lt;/code&gt;s with “pragmatic” &lt;code&gt;parMap&lt;/code&gt;, &lt;code&gt;mapAsync&lt;/code&gt;, or even &lt;code&gt;parTraverse&lt;/code&gt; and call it a day, or maybe it’s because Scala library authors, among other things, built on top of Haskell’s findings.&lt;/p&gt;
&lt;h2&gt;
  
  
  Take-aways
&lt;/h2&gt;

&lt;p&gt;So, is there a lesson here? On one hand, I wish people would stop dumping on other languages and recite the same things.&lt;/p&gt;

&lt;p&gt;On the other hand, I, for instance, hate Ruby so much that if someone told me to learn something from Ruby, I’d tell them to…&lt;/p&gt;



&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/K76vrOzU53o"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>functional</category>
      <category>haskell</category>
      <category>scala</category>
    </item>
  </channel>
</rss>
