<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: doma.dev</title>
    <description>The latest articles on DEV Community by doma.dev (@doma).</description>
    <link>https://dev.to/doma</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%2F594021%2F90fa3fc6-ac10-46ce-aced-3abe08889acb.jpeg</url>
      <title>DEV Community: doma.dev</title>
      <link>https://dev.to/doma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/doma"/>
    <language>en</language>
    <item>
      <title>Type system innovation propagation</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Fri, 03 Sep 2021 16:30:00 +0000</pubDate>
      <link>https://dev.to/doma/type-system-innovation-propagation-43g6</link>
      <guid>https://dev.to/doma/type-system-innovation-propagation-43g6</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Incorporation of established programming language theory approaches is desired by mainstream language designers.

&lt;ul&gt;
&lt;li&gt;The fashion in which parametric polymorphism has enabled generics in Java and Go demonstrates this.&lt;/li&gt;
&lt;li&gt;Go with generics has the potential to solve the expression problem.&lt;/li&gt;
&lt;li&gt;C++ has got it right straight away and work has been done to improve parametric polymorphism to allow for ergonomic higher kinded types (generic types that themselves accept type variables).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Further work is required to further improve expressiveness and ergonomics of languages with type systems.

&lt;ul&gt;
&lt;li&gt;Most of languages with type systems lack scalable ways to deal with heterogenous data.&lt;/li&gt;
&lt;li&gt;Structure-aware features and row polymorphism asks for a wider adoption than just in PureScript.&lt;/li&gt;
&lt;li&gt;Lack of efficient structure-aware features algorithms holds back the adoption greatly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why not settle for naive or simple type systems?
&lt;/h2&gt;

&lt;p&gt;Most language designers agree that type systems should have first-class treatment in programming languages. Almost all the programming languages saw their type systems evolve to incorporate new features. In this post we'll study some of such cases and motivate the need for furthering type system R&amp;amp;D beyond what we have now at our disposal.&lt;/p&gt;

&lt;p&gt;To do that, we shall look at the history of two mainstream programming languages (Java and Go) through the lens of generic computing in said languages. In this post, when we talk about generic computing, we mean "ways to program in a type-agnostic way" or "writing a program that doesn't just work on one concrete type, but works on some class of types".&lt;/p&gt;

&lt;p&gt;Thus, generic computing is instrumental even to the most basic programming. Data structures (trees, arrays, ...) are foundational to the discipline and intrinsically generic. The challenge then, is to encode them in a type-safe way. A motivational example would be Java's "Hashtable", as seen in version 1.0, dated 7th of January, 1998.&lt;/p&gt;

&lt;h2&gt;
  
  
  Razor-sharp generic computing
&lt;/h2&gt;

&lt;p&gt;Consider its &lt;code&gt;get&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;HashtableEntry&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;table&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;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hashCode&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;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x7FFFFFFF&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&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="nc"&gt;HashtableEntry&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;Considerations for &lt;a href="https://www.youtube.com/watch?v=ybrQvs4x0Ps"&gt;the billion dollar mistake&lt;/a&gt; aside, when we talk about type safety of this snippet, we see that, on line three of it, we call method &lt;code&gt;hashCode()&lt;/code&gt; of an instance of class &lt;code&gt;Object&lt;/code&gt;. This approach to "generics" asks engineers to have a single point in the closed type hierarchy, which mandates all the necessary methods for the generic applications. This approach is a source of headache for library implementers. Even if we negotiate that using Interfaces is good enough for implementing generic programs (think, &lt;code&gt;get&lt;/code&gt; would accept &lt;code&gt;IHashable&lt;/code&gt; instead of &lt;code&gt;Object&lt;/code&gt;), the problems still exist.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upcasting (also known as generalisation, treatment of a subtype as a supertype) to an interface or an Object would result in the return value of a wider-than-needed type, which would require for downcasting (also known as specialisation, treatment of a supertype as a subtype) later on, throwing away type guarantees and creating a space for errors.&lt;/li&gt;
&lt;li&gt;Less significantly, overlapping abstract method names in interfaces without resolving facilities make generic programming via upcasting less scalable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pioneering language in the modern type systems engineering, which gave raise to Haskell and Ocaml is called "ML". ML, in mid-seventies, has introduced something called "parametric polymorphism", the idea of which is to let programmers have variables for types themselves in a similar way that programmers have variables for values. Modern Java's Hashtable uses parametric polymorphism and is said to be "polymorphic in key and value types":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Hashtable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Dictionary&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;K&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="no"&gt;V&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="nc"&gt;Cloneable&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Case study: type variables for better polymorphism
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Generic Java
&lt;/h3&gt;

&lt;p&gt;As we discussed, initial approach to generic programming in Java was to use Object, the common super-class for any Java class. &lt;a href="http://pizzacompiler.sourceforge.net/"&gt;Pizza language&lt;/a&gt;, made by Odersky (eventually, the creator of Scala) and Wadler (co-designer of Haskell), released one year after Java, was a superset of Java that was a bit more principled and allowed for type variables that would then be "erased" and translated into Object class, automating upcasting and downcasting, thus retaining type safety. It also allows to remove the problem with exponential blow-up of compiled artefacts like the one seen in C++ due to conditional code generation. More on that later.&lt;/p&gt;

&lt;p&gt;Type erasure is greatly misunderstood and some shortcomings of Java type system is misattributed to it, but it's not without its drawbacks. Most notably, one cannot use type variables in Java in to cast values to that type. I.e. &lt;code&gt;(T)x&lt;/code&gt; is not a valid expression if T is type variable. The other drawback of type erasure is that even if a generic data structure or method is parametrised with a primitive type, the overhead of boxing it (turning it into a Java class) will be carried via erasure. Note that none of the drawbacks of type erasure limit type safety, only expressiveness and performance.&lt;/p&gt;

&lt;p&gt;Wadler et al., after Pizza was released, made a minimum viable formalisation of Java, which was instrumental for eventual inclusion of generics in Java in version 1.5, in 2004.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic Go
&lt;/h3&gt;

&lt;p&gt;Go is infamous for the longest time between the release of an industrial language and getting generics. Importantly, it gave room for what I call &lt;code&gt;void *&lt;/code&gt; polymorphism. In Go circa 2021, it's &lt;code&gt;interface{}&lt;/code&gt; polymorphism and, without going into much details about why it works, we'll present you with real code that makes use of it:&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;func&lt;/span&gt; &lt;span class="n"&gt;ToBoolE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;indirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;case&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;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&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="o"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;case&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;return&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&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;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"unable to cast %#v of type %T to bool"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&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;This is clearly problematic, because usage of &lt;code&gt;interface{}&lt;/code&gt; type in programs poisons them with runtime switching over type information, unlifting the failure detection from the realm of static analysis to the realm of dynamic monitoring. Furthermore, a slight change in the acceptable types shall cause a refactoring hell! There would be no way to know, when you extend domain of your &lt;code&gt;interface{}&lt;/code&gt; function, which other functions need to have their domain also extended.&lt;/p&gt;

&lt;p&gt;Similarly to introducing generics to Java, introducing generics to Go included two stages: formalisation and implementation proposal. Given the experience of the team who is behind generics in Go experience in the matter (a lot of it is thanks to having Wadler on board), in case of Go, proper formalisation came first, it was implemented later.&lt;/p&gt;

&lt;p&gt;Another reason for starting with formalisation first in case of Go, perhaps, is rooted in the fact that adding parametric polymorphism to Go is harder than doing so in Java. Indeed, one of the great features of Go language is that its struct-interface supertyping is open.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package s

type Nil struct{}

func (n *Nil)Show() string {
        return "{}"
}

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

&lt;/div&gt;



&lt;p&gt;A structure with a function in a package defined independently can indeed happen to implement an interface defined in another package:&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;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"fmt"&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s"&gt;"doma.dev/s"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Shower&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Shower&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;var&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;Nil&lt;/span&gt;&lt;span class="p"&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="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;x&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;Further complication which warranted careful planning for this feature was that the goal was to use code generation (fancy word for which is "monomoprhisation" because poly-morphic things spawn a bunch of mono-morphic things), instead of type erasure, to achieve more versatile generics at the expense of binary size.&lt;/p&gt;

&lt;p&gt;Finally, &lt;a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md"&gt;a proposal&lt;/a&gt; that adds generics with constraints (which programmers can create and use in their code) was implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go and expression problem test
&lt;/h3&gt;

&lt;p&gt;Besides, Generic Go, as currently implemented &lt;em&gt;almost&lt;/em&gt; passes the expression problem test.&lt;/p&gt;

&lt;p&gt;The expression problem, essentially, states that without changing the existing source code in modules (except for the integration module) and while preserving type safety, codebase is extendable with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a new type, implementing all existing functions;&lt;/li&gt;
&lt;li&gt;a new function over all existing types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The expression problem test is then formulated as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work with expressions for a calculator DSL that builds up arithmetic expressions and then evaluates them (hence the name of "expression problem").&lt;/li&gt;
&lt;li&gt;Start with an expression type case "constant" which holds a value of some primitive numeric type.&lt;/li&gt;
&lt;li&gt;Implement a function "evaluate" that takes an expression and returns the corresponding value of the primitive numeric type.&lt;/li&gt;
&lt;li&gt;Implement "evaluate" for "constant".&lt;/li&gt;
&lt;li&gt;Encode expression "plus" that denotes adding up two expressions.&lt;/li&gt;
&lt;li&gt;Extend "evaluate" to work on it without changing other modules.&lt;/li&gt;
&lt;li&gt;Implement "to string" function for both expressions ("plus" and "constant") without changing other modules.&lt;/li&gt;
&lt;li&gt;In the integration module, demonstrate that any function is callable over any defined type case.&lt;/li&gt;
&lt;li&gt;Erase all code for "plus" and "to string".&lt;/li&gt;
&lt;li&gt;Reimplement "to string" first.&lt;/li&gt;
&lt;li&gt;Reimplement "plus" second, then extending "evaluate" and "to string".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If generic constraint narrowing would be possible in Generic Go as implemented (it was planned to be possible in the original research), we would have been able to write the following code to solve the expression problem in Go:&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="c"&gt;// package A at time 0&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExprConst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;UnConst&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Currently impossible because receiver arguments have to have exactly the&lt;/span&gt;
&lt;span class="c"&gt;// same type signature, including specificity of the type parameters, as their&lt;/span&gt;
&lt;span class="c"&gt;// struct declarations.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;ExprConst&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="n"&gt;Eval&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnConst&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package A at time 0&lt;/span&gt;

&lt;span class="c"&gt;// package E at time 0&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Evaler&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Eval&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="c"&gt;// end of package E at time 0&lt;/span&gt;

&lt;span class="c"&gt;// package P at time 1&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Left&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;
    &lt;span class="n"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Currently impossible&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Evaler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Evaler&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Eval&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package P at time 1&lt;/span&gt;

&lt;span class="c"&gt;// package E at time 2&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Evaler&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Shower&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package E at time 2&lt;/span&gt;

&lt;span class="c"&gt;// package A at time 2&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExprConst&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;ExprConst&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="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Const&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package A at time 2&lt;/span&gt;

&lt;span class="c"&gt;// package P at time 2&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Shower&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Shower&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"( %s + %s )"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&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;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&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="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package P&lt;/span&gt;

&lt;span class="c"&gt;// package main at time 2&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Expr&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Evaler&lt;/span&gt;
    &lt;span class="n"&gt;Shower&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;Expr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Expr&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt;
        &lt;span class="n"&gt;ExprPlus&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Expr&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt;
            &lt;span class="n"&gt;ExprConst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Expr&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;ExprConst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Expr&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;ExprConst&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Expr&lt;/span&gt;&lt;span class="p"&gt;]{&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d = %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eval&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;e&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="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// end of package main&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then, when one would run this, the output would be &lt;code&gt;42 = ( ( 30 + 11 ) + 1 )&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quoting Robert Griesemer, one of the contributors to the FG paper and one of the main implementers of Generic Go&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even though we can type-check that, we don't know to implement it efficiently in the presence of interfaces (which would also have methods with corresponding type parameters).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe some day...&lt;/p&gt;

&lt;h2&gt;
  
  
  More evidence of usefulness of R&amp;amp;D in type systems
&lt;/h2&gt;

&lt;p&gt;There are many other examples that demonstrate adoption of programming language theory results in mainstream languages. To name a few:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rediscovery of higher kinded types in C++ (something very little type systems allow for natively), and a long process of evolution to make them ergonomic.&lt;/li&gt;
&lt;li&gt;Design and inclusion of higher kinded types into Scala by Martin Odersky.&lt;/li&gt;
&lt;li&gt;Allowing for ergonomic higher order functions in C++ and Java&lt;/li&gt;
&lt;li&gt;Function type treatment in mainstream languages, from Golang to Rust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also an innovation that is on the verge of breaking through into mainstream languages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure-aware type systems and row polymorphism
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/doma/why-type-systems-matter-4lid"&gt;As we discussed&lt;/a&gt;, type systems, by definition, limit the expressiveness of languages. And yet, they are well worth it as far as budgets are concerned. Let's start this post with exploring a classical expressiveness shortcoming of languages with type systems: the problem of operating on heterogenous data.&lt;/p&gt;

&lt;p&gt;Imagine we need to store a hierarchy of countries and cities in the same tree. An untyped approach would be simple: make distinct objects for countries, cities, neighbourhoods and then add &lt;code&gt;children&lt;/code&gt; field to each, putting necessary objects on lower levels of the hierarchy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Riga&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;longestStreet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Brivibas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Zagreb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;longestStreet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ilica&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;country1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Latvia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ownName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Latvija&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;capital&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;city1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;country2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Croatia&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ownName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hrvatska&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;capital&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;city2&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city11&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Zilupe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;longestStreet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Brivibas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;city22&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Split&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;longestStreet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Domovinskog Rata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Earth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="p"&gt;[{...&lt;/span&gt;&lt;span class="nx"&gt;country1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;city1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city11&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
      &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;country2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;children&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;city2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;city22&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;Naively, the same can be achieved by having a tree type, parametrised with a union type that encodes either a City or a Country.&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;World&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;World&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="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Country&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;capital&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;City&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;City&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;City&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;longestStreet&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="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;W&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;World&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;C&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;City&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt; &lt;span class="kt"&gt;City&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;However, quite some problems arise when we want to extend encoding to also capture streets, for instance. Our union type shall change along with type definition for City. This topic is far from being trivial to solve in a polymorphic fashion in typed languages. There is &lt;a href="https://qspace.library.queensu.ca/bitstream/handle/1974/672/Huang_Freeman_Y_200708_PhD.pdf?sequence=1&amp;amp;isAllowed=y"&gt;modern research&lt;/a&gt; that shows that it's doable by introducing "pattern structures" into structure-aware type systems.&lt;/p&gt;

&lt;p&gt;Relevant to the issue of heterogenity, solving problems such as capability tracking and diverse effect systems, is row polymorphism. It's another structure-aware approach to polymorphism, which is said to work on types with rows (records), and allows to define functions that are polymorphic in something except for some rows. In our example, a row-polymorphic function over our structure, could perhaps ask for any type for which &lt;code&gt;name :: Text&lt;/code&gt; is defined, along with, perhaps, non-zero other rows. It would then accept anything in our heterogenous structure, since everything is named. If it feels to you like this walks like duck typing and quacks like duck typing then yes, you are right. It is exactly a way to formalise duck typing and introduce it into the type systems. It is a common theme, however, that for PLT to be adopted in the industry, systems need to be engineered that implement the theory. But when you introduce one feature to a system, you trade off ease of introduction of other features (this is why we don't have and we will never have a universal language that is good at everything). In case of row polymorphism, the challenge is an &lt;a href="https://www.reddit.com/r/haskell/comments/8uhj1f/what_is_the_status_on_structural_typing_row_types/e1fu2g2/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3"&gt;efficient representation of records&lt;/a&gt;. Gladly, default implementation of PureScript piggy-backs node.js efficiency. We expect row polymorphism to make its way into functional programming languages from already existing implementations in PureScript and an industrial laboratory language Ermine and eventually be adopted in mainstream languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notable ommissions
&lt;/h2&gt;

&lt;p&gt;It is hard to provide full survey of polymorphism and tangent topics in one little blog post. This is why we had to pick our battles. We have considered, but decided to ommit or mention just briefly, the following subjects (with links to introductory posts about them):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://typelevel.org/blog/2016/08/21/hkts-moving-forward.html"&gt;Importance of higher-kinded types&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://okmij.org/ftp/tagless-final/index.html"&gt;Using tagless representations to pass expression problem test&lt;/a&gt; (&lt;a href="https://serokell.io/blog/introduction-tagless-final"&gt;tagless final for intermediate haskellers&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://doma.2038.io/library/Practical_type_inference_for_polymorphic_recursion.pdf"&gt;Using polymorphic recursion for typing heterogenous data&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Parting words
&lt;/h2&gt;

&lt;p&gt;In most mainstream languages, existing facilities to boost expressiveness of type system is sufficient in majority of cases without sacrificing guarantees. If you find yourself needing more, sometimes introducing refactoring loops into your feature implementation process can be wise. In well-typed systems, refactoring is cheap and introducing such loops be detrimental to time to market compared to using untyped approaches. That said, for the sake of accepting many potential architectures that would be possible if type systems were more rich, we need to press on as a community and create compilers that take novel research ideas or ideas from other languages in a continuous struggle to unify those into ergonomc systems. Furthermore, along with regaining expressiveness, this work often is capable to &lt;a href="https://dev.to/serokell/why-dependent-haskell-is-the-future-of-software-development-574l-temp-slug-7645490"&gt;tighten the compile-time guarantees&lt;/a&gt;. More about it in the upcoming blog post.&lt;/p&gt;

&lt;p&gt;All in all, we think that exploration of repeated success of adoption of parametric polymorphism by mainstream languages does good enough job to motivate businesses to look at the proceedings in the field!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Why type systems matter</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Thu, 26 Aug 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/doma/why-type-systems-matter-4lid</link>
      <guid>https://dev.to/doma/why-type-systems-matter-4lid</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Computer programmers expect their language environments to reject bad programs. It's largely done with lightweight formal methods.&lt;/li&gt;
&lt;li&gt;Runtime monitoring (the thing that tells you that &lt;code&gt;undefined is not a funciton&lt;/code&gt;) is an example of such a formal method.&lt;/li&gt;
&lt;li&gt;A type system is also an example of such a formal method.&lt;/li&gt;
&lt;li&gt;Type systems target a range of properties deemed as "bad", for which it is guaranteed that programs having those are rejected.&lt;/li&gt;
&lt;li&gt;This may and does result in "good" programs having "bad" properties being rejected. We say that it means that type systems limit expresiveness of a language.&lt;/li&gt;
&lt;li&gt;"If it compiles, it works" is a dangerous misconception, but there is a synergy between correctness and passing a type check.&lt;/li&gt;
&lt;li&gt;Alternative to using type systems, however, is less feasible for adequately-budgeted developments because it moves error detection to later stages of system's lifecycle, resulting in significantly larger costs.&lt;/li&gt;
&lt;li&gt;Type systems are also great for rapid prototyping, technical validation and deriving specifications from requirements.&lt;/li&gt;
&lt;li&gt;Type systems allow you to test for only truly run-time faults, which are more often than not related to side-effects.&lt;/li&gt;
&lt;li&gt;If your organisation can cope with the possible friction that type systems bring, not using type systems is irresponsible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A fistful of formal methods
&lt;/h2&gt;

&lt;p&gt;We want our programming language environments at large to be able to tell well-behaved programs from those that behave poorly. There are several ways to achieve this.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Runtime monitoring, which considers things like operations on incompatible objects (a la Python and JavaScript) and underappreciated contract programming based on preconditions and postconditions, as well as invariant checking (a la &lt;a href="https://www.eiffel.org/doc/solutions/Design_by_Contract_and_Assertions"&gt;Eiffel&lt;/a&gt; and &lt;a href="https://dlang.org/spec/contracts.html"&gt;DLang&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some will remember model-driven engineering with UML modelling (my Vim highlighted "UML" as a non-existent word! It brings me joy). Automatically deriving constraints from such models and rejecting models that are self-contradicting or breaking some constraints. (a la &lt;a href="https://ieeexplore.ieee.org/document/6229788"&gt;EMFtoCSP&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both digital and &lt;a href="https://d-nb.info/1010333739/34"&gt;analog&lt;/a&gt; circuits can be accepted or rejected based on automatically derived finite state machine models and checking for desired properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type systems for rejecting classes of poorly-behaved programs statically, during compilation (a la Java, Haskell).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A rather interesting observation is that these discriminators should be reproducible, which calls for underlying formalisms. Furthermore, it's preferred that domain experts (JavaScript programmers, UML architects, embedded systems engineers) can reap benefits from those. That property is called "lightweight" in culture. When we put these considerations together, we see that all of these things, including JavaScript's runtime monitoring, which many people may deem as basic, are lightweight formal methods! Not scary at all.&lt;/p&gt;

&lt;p&gt;Not all formal methods, however, are made for the same reason and not everything achievable with one can be achieved with another. To illustrate that, consider the following use-case: we build up an array of validation functions and then, at the validation site we call them one by one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01 |    let module1 = {
02 |      defaultValidators: [
03 |        (x) =&amp;gt; 2 == x.split(' ').length,
04 |      ],
05 |      validate: (input) =&amp;gt; (fs) =&amp;gt;
06 |        fs.reduce((acc, f) =&amp;gt; acc &amp;amp;&amp;amp; f(input), true),
07 |    };
08 |
09 |    let module2 = {
10 |      alsoCapitalised: [
11 |        (x) =&amp;gt;
12 |           x.split(' ').reduce(
13 |             (acc, x) =&amp;gt; acc &amp;amp;&amp;amp; (/[A-Z]/.test(x[0])), true
14 |           )
15 |      ] + module1.defaultValidators,
16 |    }
17 |
18 |    let main = {
19 |      main: (input) =&amp;gt; {
20 |        let validators = module2.alsoCapitalised;
21 |        if (module1.validate(input)(validators)) {
22 |          console.log("It's time to open the door");
23 |        }
24 |      }
25 |    }
26 |
27 |    main.main("Viktor Tsoi");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run this code, the following error will be reported:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught TypeError: fs.reduce is not a function
    validate debugger eval code:6
    main debugger eval code:21
    &amp;lt;anonymous&amp;gt; debugger eval code:27

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

&lt;/div&gt;



&lt;p&gt;The true place where the error happens is line 15. Getting there from lines 6 and 21 would probably require a little bit of debugging, especially in a real project. Indeed, the error happens due to nonsense operation &lt;code&gt;+&lt;/code&gt; over two arrays. Let's fix it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15 | ].concat(module1.defaultValidators),

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

&lt;/div&gt;



&lt;p&gt;When we run the code again, we get the expected message in the log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;It's time to open the door

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

&lt;/div&gt;



&lt;p&gt;Let's compare runtime monitoring with a type system.&lt;/p&gt;

&lt;p&gt;Here's the code with the same error in Haskell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01 | {-# LANGUAGE OverloadedStrings #-}
02 | import qualified Data.Text as T
03 | import Data.Text( Text )
04 | import Data.Char( isUpper )
05 |
06 | defaultValidators :: [Text -&amp;gt; Bool]
07 | defaultValidators = [\x -&amp;gt; 2 == (length $ T.splitOn " " x)]
08 |
09 | validate :: Text -&amp;gt; [Text -&amp;gt; Bool] -&amp;gt; Bool
10 | validate input fs = foldl (\acc f -&amp;gt; acc &amp;amp;&amp;amp; f input) True fs
11 |
12 | alsoCapitalised :: [Text -&amp;gt; Bool]
13 | alsoCapitalised = [\x -&amp;gt; foldl (\acc w -&amp;gt; acc &amp;amp;&amp;amp; (isUpper $ T.head w))
14 |                                True
15 |                                (T.splitOn " " x)] + defaultValidators
16 |
17 | main :: IO ()
18 | main =
19 |   case validate input defaultValidators of
20 |     True -&amp;gt; putStrLn "It's time to open the door"
21 |     _    -&amp;gt; putStrLn "Close the door behind me"
22 |   where
23 |     input = "Viktor Tsoi"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we try to compile it, we're going to get an error that says exactly what is wrong. To be able to apply &lt;code&gt;+&lt;/code&gt;, operands had to be classified as numbers via typeclass &lt;code&gt;Num&lt;/code&gt;. This typeclass doesn't include lists of validator functions. Note that if we would want to define addition on such values, we would be able to, by providing an appropriate instance of &lt;code&gt;Num&lt;/code&gt;. But it's a rather horrible idea, so we'll fix the bug instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/tmp/hi.hs:13:19: error:
    No instance for (Num [Text -&amp;gt; Bool]) arising from a use of '+'

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

&lt;/div&gt;



&lt;p&gt;With this error, we quickly can replace line 15 with one using &lt;code&gt;++&lt;/code&gt;, the list concatenation operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15 | (T.splitOn " " x)] ++ defaultValidators

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

&lt;/div&gt;



&lt;p&gt;When we run this one, we get the correct result!&lt;/p&gt;

&lt;p&gt;Static checking allows us to catch many classes of errors like this one early, which saves a lot of money, since—as systems engineering teaches us—the cost of fixing a fault in a system grows exponentially as a function of how far it is from the requirement gathering stage in the lifecycle of a system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of using type systems
&lt;/h3&gt;

&lt;p&gt;Type systems come in different shapes and sizes: different type systems may be geared to eliminate different classes of incorrect programs. However, most type systems—collaterally—eliminate programmers' errors such as incomplete case analyses, mismatched units, et cetera. For example, if we get rid of line 21 in the Haskell listing entirely, in a well-configured GHC (which treats warnings as errors and warns about everything "suspicious), we'll get the following error, indicating incomplete case analysis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/tmp/hi.hs:19:3: error: [-Wincomplete-patterns, -Werror=incomplete-patterns]
    Pattern match(es) are non-exhaustive
    In a case alternative: Patterns not matched: False
   |
19 | case validate input defaultValidators of
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

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

&lt;/div&gt;



&lt;p&gt;Of course, it's impossible to reap this benefit without a certain wit and discipline. I like to call that discipline "tight typing", many Haskellers call it "having as concrete data structures as possible" (it's an elaboration of the mantra "abstract functions, concrete data"). For instance, the &lt;code&gt;DummyTag&lt;/code&gt; type you have seen earlier is loose, because it is used in the places of the model accepting types with incompatible terms. Quoting my colleague:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nothing prevents you to subtract height from pressure if both of those are encoded as Float.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Type checkers are powerful refactoring tools. Anecdotally, at work, once we had to restructure approximately fifty modules while separating part of those into a library and fusing arguments into structures in another part of those. The whole refactoring was done and released by one person in one working day. It would have been impossible without a type checker to ensure the completeness of said refactoring. Another anecdote comes from my colleague:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When I worked for AlphaSheets.com (a startup "acquihired" by Google), I refactored the whole codebase, threading through an App monad instead of IO. I did this for a week in part due to painful and regular rebasing onto the main branch. But when the thing was compiled, the only tests that failed were the ones covering a place that was stubbed with undefined.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notorious for a steep learning curve and perceived feature development slow-down, languages with type systems—granted a certain engineering savviness—can serve as amazing facilitators of rapid prototyping. The goal of prototyping is often to figure out the best specification for the requirements at hand. Expressive type systems often allow encoding relationships between domain entities without writing complex business logic. If one views types as claims that something is possible and values of said types as proofs that it indeed is possible, this approach makes a lot of sense. Of course, mileage can vary and it works better the fewer side-effects there are in a system, but remember that you can simulate side effects via type encodings too! For instance, instead of figuring out a proper way to do cryptography while prototyping, we can encode an interface of a crypto-system and populate it with dummy functions, complying with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data PKC pass sk pk slip sig sigmsg enc plain cipher = PKC
  { -- | Initial key derivation function
    kdf :: pass -&amp;gt; (sk, pk, slip),
    -- | Rederive with kdf
    rekdf :: slip -&amp;gt; pass -&amp;gt; (sk, pk),
    -- | Sign data with key @sk@ and produce a detached @signature@
    -- possibly containing @pk@ for verification.
    sign :: sigmsg -&amp;gt; (sk, pk) -&amp;gt; signature pk,
    -- | Verifies @signature@ container's validity.
    verify :: sigmsg -&amp;gt; signature pk -&amp;gt; Bool,
    -- | Encrypt data of type @plain@ to the key @pk@ and produce @encrypted@
    -- containing @cipher@.
    encrypt :: plain -&amp;gt; pk -&amp;gt; encrypted pk cipher,
    -- | Decrypts @cipher@, contained in an @encrypted@ container into @plain@.
    decrypt :: encrypted pk cipher -&amp;gt; sk -&amp;gt; Maybe plain
  }

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

&lt;/div&gt;



&lt;p&gt;This is a model of public key cryptography. Populating this model with functions would, together with tests that verify correct behaviours and error handling of a cryptosystem, serve as proof of the possibility of a correct implementation of public key cryptography in Haskell. Perhaps more importantly, it would also provide an interactive specification for doing so, perhaps even in another language! Let's give an example of some functions slotting into that model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data DummyTag = DummySK | DummyPK | DummySlip
  deriving (Show, Eq)

-- | Note that we abuse the fact that in dummy implementation
-- secret key and public key are both represented with a
-- DummyTagged type alias to embed secret key together with
-- the message.
newtype DummySigned msg key = DummySigned {sig :: (key, (key, msg))}
  deriving (Show, Eq)

-- ...

type DummyTagged = (DummyTag, ByteString)

-- ...

dummyKdf :: ByteString -&amp;gt; IO (Maybe (DummyTagged, DummyTagged, DummyTagged))
dummyKdf pass = pure $ Just ((DummyPK, pass), (DummySK, pass), (DummySlip, pass))

dummyRekdf :: DummyTagged -&amp;gt; ByteString -&amp;gt; Maybe (DummyTagged, DummyTagged)
dummyRekdf (DummySlip, x) pass =
  go (x == pass)
  where
    go True = Just ((DummyPK, pass), (DummySK, pass))
    go False = Nothing
dummyRekdf _ _ = error "DummySlip expected in the 1st argument"

-- ...

dummySign :: (DummyTagged, DummyTagged) -&amp;gt; msg -&amp;gt; DummySigned msg DummyTagged
dummySign (verificationKey@(DummyPK, _), signingKey@(DummySK, _)) blob =
  DummySigned (verificationKey, (signingKey, blob))
dummySign _ _ = error "The first argument has to be a tuple of DummySK and DummyPK"

-- | Note that we're not comparing public key with secret key
-- but rather compare embedded bytestrings which match if the keys
-- were derived from the same password by kdf
dummyVerify :: Eq a =&amp;gt; DummySigned a DummyTagged -&amp;gt; a -&amp;gt; Bool
dummyVerify (DummySigned ((DummyPK, signedAs), ((DummySK, signedWith), signedWhat))) candidate =
  (signedAs == signedWith) &amp;amp;&amp;amp; (candidate == signedWhat)

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

&lt;/div&gt;



&lt;p&gt;Now to keep prototyping, we just need to instantiate PKC data type with this collection of functions. Later on, when we switch to a real cryptographic system, we will use it to make another value of type PKC. If all the properties of the initial prototype were preserved, it shall serve as proof to the claim that "production public key cryptographic systems exist as modelled". We can and should verify that early, but not too early to slow the prototyping down. Similarly, HTTP client-server interactions can be modelled. After the prototype is completed, one will end up with a runnable, compilable specification for the software they're about to write. What's fairly amazing is that if the company doesn't want to switch from Haskell (or whichever strongly-typed language they were using to model) to another language for the actual product, they can repurpose this prototype for an incremental rewrite into an MVP!&lt;/p&gt;

&lt;p&gt;Now to the last, but not the least important benefit of type systems! These days, usage of higher-order and anonymous functions is prominent even in more conservative ecosystems like Java's. Type systems greatly assist in reasoning about the code's overall behaviour. In general, type systems are one of many tools for writing self-documenting code. An illustration for those, who (like me) keep forgetting the order of the accumulator and an the iterated value in reducers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prelude&amp;gt; :t foldl
foldl :: Foldable t =&amp;gt; (b -&amp;gt; a -&amp;gt; b) -&amp;gt; b -&amp;gt; t a -&amp;gt; b

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

&lt;/div&gt;



&lt;p&gt;Yeah, if the language's ecosystem is tightly integrated with the underlying type system, amazing things are possible, from simple type signature lookups at your fingertips to full-blown type signature search engines like &lt;a href="https://hoogle.haskell.org/"&gt;Hoogle&lt;/a&gt; and Serokell's &lt;a href="https://hackage-search.serokell.io/"&gt;hackage-search&lt;/a&gt;. Conversely, if the language ecosystem evolved independently from type system, such as TypeScript and Dialyzer extending their respective languages with success typings, likely, self-documenting benefits and improved discoverability will be way less pronounced, if at all.&lt;/p&gt;

&lt;p&gt;Type systems also enable and encourage writing composable code, meaning that the programmers are nudged towards writing well-structured and modular codebases, no matter what is the unit of modularity: a Java class or a Haskell module. Of course, there are ways to write spaghetti code in any language, but it's harder when the whole ecosystem imposes structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawbacks of type systems
&lt;/h3&gt;

&lt;p&gt;Type systems aren't entirely free. Both the users (programmers) and the computer itself have to do extra work to write a program that would be accepted by a language with a type system. Sometimes, that work takes non-trivial amounts of computational time, but in practice, it's seldom more computationally intense than, say, code generation via templates.&lt;/p&gt;

&lt;p&gt;Also, not quite a drawback, but rather something many people don't understand about type systems. There's an "if it compiles, it works" meme, but it's extremely misleading. Type systems, by their static nature, can't prove the presence of features of a program, only absence. But this yields a couple of actual drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With type systems, you almost always pick your fights. Languages geared towards eliminating one kind of bad program behaviours won't eliminate another, perhaps, side-stepping it altogether by deferring it to the language runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scrutiny, thus power, of type systems is always in tension with expressiveness, which is understood as the measure of the programs that are well-behaved at runtime, which are rejected by the type checker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sometimes complex type checking algorithms rely on heuristics, which limit expressiveness in ways, &lt;a href="https://www.youtube.com/watch?v=jNbb5JVuq-o"&gt;unexpected by the user&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bottom line
&lt;/h3&gt;

&lt;p&gt;We'll end this article with a nice heuristic for architects to think about using type systems. Perform the following thought experiment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Approximate how much would it cost to write, deploy and run a 100%-coverage random testing system, searching for runtime errors (in our JS example, it would be a test making sure that there is no validator crashed by a string and there is no call in the program that crashes it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Approximate how much would it cost to train developers to use a "tight" type system, which would give the same sort of guarantees "for free" and in static fashion (many different kinds of tests are still needed in this approach, but the tests we've described in p.1 are given to us for free by the type checker).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If cost 2 is even comparable to, let alone lower than, cost 1, going for using type systems to refuse incorrect programs is warranted. Quoting "The Toyota Way":&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Focusing on quality actually reduced cost more than focusing only on cost.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Everything you need to know to write safe bash scripts</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Fri, 09 Apr 2021 13:32:00 +0000</pubDate>
      <link>https://dev.to/doma/everything-you-need-to-know-to-write-safe-bash-scripts-17gg</link>
      <guid>https://dev.to/doma/everything-you-need-to-know-to-write-safe-bash-scripts-17gg</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When to resort to shell scripts

&lt;ul&gt;
&lt;li&gt;Portability is important&lt;/li&gt;
&lt;li&gt;Problem at hand is compact&lt;/li&gt;
&lt;li&gt;File system interaction&lt;/li&gt;
&lt;li&gt;Command-line program automation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;When to search for an alternative

&lt;ul&gt;
&lt;li&gt;Extensibility is required&lt;/li&gt;
&lt;li&gt;Coding mission-critical stuff&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Shell scripting is dangerous, use shellcheck and limit yourself in idioms used&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Computer consoles are the second most important UX improvement in computing, surpassed only by window managers. Consoles went a long way from allowing the computer user to enter programs to be executed by a single-process operating system to converting them into toolboxes. Gladly, most of it was happening in Bell Labs under the supervision of the unstoppable innovator &lt;a href="https://en.wikipedia.org/wiki/Douglas_McIlroy" rel="noopener noreferrer"&gt;Douglas McIlroy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://web.archive.org/web/20201004064728/https://www.multicians.org/mgs.html" rel="noopener noreferrer"&gt;Multics "shell"&lt;/a&gt;, just like inputs on other terminal-enabled computers of that era, was an instrument to accept a program and execute it on the Multics OS, the predecessor of UNIX. The earliest versions of the Multics shell already had input/output redirection. It wasn't until Douglas McIlroy &lt;a href="https://corecursive.com/021-gods-programming-language-with-philip-wadler/" rel="noopener noreferrer"&gt;discovered (not invented)&lt;/a&gt; command pipelines, it became a golden standard across all the operating systems.&lt;/p&gt;

&lt;p&gt;Pipelining and UNIX philosophy is allowing for writing small problem-specific programs that can be later composed. But the biggest reason for the usage of UNIX shell scripts in 2021 is portability. Indeed, every modern system has a UNIX shell readily available. Furthermore, often making a reasonably well-written shell script is "good enough for the job". But how does one do that? Let's explore the answer to this question, assuming that the reader already knows the &lt;a href="https://livecodestream.dev/post/introduction-to-bash-for-beginners/" rel="noopener noreferrer"&gt;very basics of shell scripting&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal shell scripts in bash
&lt;/h2&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%2Fctf.cdn.doma.dev%2Fthou-shall-not-establish-bumblebee.jpg" 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%2Fctf.cdn.doma.dev%2Fthou-shall-not-establish-bumblebee.jpg" alt="An Reannissance meme with an evil-looking man saying "&gt;&lt;/a&gt;Let's get the most important consideration out of the way. Writing secure and reliable shell scripts is &lt;a href="https://www.netmeister.org/blog/MrMEEE/backup.html" rel="noopener noreferrer"&gt;almost impossible&lt;/a&gt;. The least one can do is to use &lt;a href="https://github.com/koalaman/shellcheck" rel="noopener noreferrer"&gt;&lt;code&gt;shellcheck&lt;/code&gt;&lt;/a&gt;, which has &lt;a href="https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck" rel="noopener noreferrer"&gt;integration with VSCode&lt;/a&gt;. Furthermore, be very disciplined with user inputs and do your best to quote every argument that has a variable in it.&lt;/p&gt;

&lt;p&gt;Alright, with that out of the way, let's talk about step-by-step items one has to do to make a reasonable shell script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up your shell environment
&lt;/h3&gt;

&lt;p&gt;Before starting programming shells, we need to first determine which shell scripting language will we use. There are three schools of thought about this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;bash&lt;/code&gt; by default. Bash is a reasonable middle ground between having a lot of features and being portable since it is shipped with each of the popular OS.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;sh&lt;/code&gt; by default and &lt;code&gt;bash&lt;/code&gt; when advanced features are needed. This is a purist approach. It offers the most portability but requires distinguishing between basic features and bash-exclusive features.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;zsh&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt; or some other "hipster" shell for everything. I'm mentioning this school of thought for completeness. Since it breaks portability, people who pick this option may just as well code in Python.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As one can guess, we suggest simply using &lt;code&gt;bash&lt;/code&gt; for everything. Of course, Apple seems to be deprecating &lt;code&gt;bash&lt;/code&gt; as the default shell, but it's not going anywhere from mac os systems. Conversely, Windows 10 has support for reasonable &lt;code&gt;bash&lt;/code&gt; integration with its WSL programme. It requires some setup, but these days WSL2 seems to become the default for Windows development.&lt;/p&gt;

&lt;p&gt;Besides, &lt;code&gt;bash&lt;/code&gt; scripts have fine-grained built-in support for lowering the impact of the inevitable bugs. While setting up your shell, we suggest you use the following &lt;a href="https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin" rel="noopener noreferrer"&gt;options&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#!/usr/bin/env bash
set -euo pipefail

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

&lt;/div&gt;



&lt;p&gt;Optionally add &lt;code&gt;-x&lt;/code&gt; for easier debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Command line argument processing
&lt;/h3&gt;

&lt;p&gt;If you, for some reason, want to use shell to write something huge like &lt;a href="https://github.com/manpages/issues-legacy" rel="noopener noreferrer"&gt;a full-blown issue tracker with git backend&lt;/a&gt;, you'll need to use &lt;a href="https://stackoverflow.com/questions/402377/using-getopts-to-process-long-and-short-command-line-options/7948533#7948533" rel="noopener noreferrer"&gt;&lt;code&gt;getopts&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://github.com/manpages/issues-legacy/blob/master/issues#L30" rel="noopener noreferrer"&gt;make your own despatch system&lt;/a&gt;. In this post, however, we shall consider simple argument processing. We heavily advocate for short and concise scripts that do one thing and one thing only, after all.&lt;/p&gt;

&lt;p&gt;First things first, let's see how to print help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if [["$1" == "--help" || "$1" == "-h"]]; then
  cat &amp;lt;&amp;lt;EOH
frgtmv: for each file read from STDIN, forget its filename entirely or amend part of it.
...
''frgtmv'' will then ''mv'' each of these files to ''\$(date +'%Y%m%d%H%M%S%N')'', preserving the file extension.
...
EOH
  exit
fi

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

&lt;/div&gt;



&lt;p&gt;Key points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We're using &lt;code&gt;&amp;lt;&amp;lt;EOH / EOH&lt;/code&gt; "heredoc" syntax and make sure that we don't indent the lines under it.&lt;/li&gt;
&lt;li&gt;We're escaping special characters like &lt;code&gt;$&lt;/code&gt; with a backslash. If we wouldn't, bash would evaluate internals in a subshell.&lt;/li&gt;
&lt;li&gt;Don't forget to &lt;code&gt;exit&lt;/code&gt; after printing the help!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's use &lt;code&gt;-n&lt;/code&gt;, a predicate checking if a variable is set, to prepare the variables needed. Often we want to set up defaults at the beginning of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
_mode="forget"
_pattern_from=""
_replace_with=""

if [-n "$1"]; then
  _mode="amend"
  _pattern_from="$1"
fi

if [-n "$2"]; then
  _replace_with="$2"
fi

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

&lt;/div&gt;



&lt;p&gt;Sometimes you would need to exit if an argument is not supplied. We use &lt;code&gt;-z&lt;/code&gt; that checks if a string is not empty for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# Exit if file or directory is not submitted or not a valid file or directory
if [-z "$1"]; then
  echo "We really need the first argument"
  exit 228
fi

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  STDIN, pipes and GNU parallel
&lt;/h3&gt;

&lt;p&gt;Sometimes you need to receive input from STDIN through a pipe or user input. It's done using &lt;code&gt;read -r&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
while read -r _x; do
  mv -v "$_x" "$(date +'%Y%m%d%H%M%S%N').${_x#*.}"
done

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

&lt;/div&gt;



&lt;p&gt;If you care about performance more than about portability, use &lt;code&gt;cat -&lt;/code&gt; to pass your STDIN to GNU parallel, following this pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function forget() {
  mv -v "$2" "$(date +'%Y%m%d%H%M%S%N').$1.${2#*.}"
}
export -f forget # (A)

if [[$_mode == "forget"]]; then
  cat - | parallel forget {%} {} # (B)
fi

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

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;(A)&lt;/code&gt;, the parallel payload is implemented as a bash function. Notice the &lt;code&gt;export&lt;/code&gt; statement! We suggest writing payloads that receive two variables: the parallel job ID (&lt;code&gt;{%}&lt;/code&gt;) and the currently read out item from the STDIN stream (&lt;code&gt;{}&lt;/code&gt;). The payload is called from &lt;code&gt;(B)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here are some interesting &lt;code&gt;parallel&lt;/code&gt; techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--keep-order&lt;/code&gt; to guarantee that the order of the input will be kept. Requires several file handles per input, which may turn out to be a bottle-neck.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find . -print0 | parallel -0 f {}&lt;/code&gt; to work in null-terminated mode.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;parallel 'echo "{%}:{1}:{2}";' ::: 1 2 ::: a b c&lt;/code&gt; will prarallelise a Cartesian product of input sets {1,2} × {a,b,c}.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bash parameter expansion
&lt;/h3&gt;

&lt;p&gt;Confusing many, if not all new shell users, "&lt;a href="https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html" rel="noopener noreferrer"&gt;parameter expansion&lt;/a&gt;" has a veil of mystery around it. In our humble opinion, there are several causes for this effect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parameter expansion is a blanket name that unites accessing values and substituting values.&lt;/li&gt;
&lt;li&gt;Within these use-cases, there is a myriad of conditional behaviours and they are decided based on the kind of parameter.&lt;/li&gt;
&lt;li&gt;There isn't much expansion going on. Word "expanded" is simply an arcane way to say "reduced to a value".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's start from the beginning. A parameter in bash is either a variable (like &lt;code&gt;$HOME&lt;/code&gt;), a positional "argument" parameter (like &lt;code&gt;$1&lt;/code&gt;), or a special parameter (like &lt;code&gt;$@&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;"Expansion" is the process of &lt;a href="https://en.wikipedia.org/wiki/Reduction_strategy_(lambda_calculus)" rel="noopener noreferrer"&gt;reduction&lt;/a&gt; of parameters to values. Variables expand in the way one would expect from variables.&lt;a href="https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html" rel="noopener noreferrer"&gt;Special parameters&lt;/a&gt;, however, can have context-dependent expansions. Expansions have special syntaxes to tack on additional computations like string substitution, length calculation, etc.&lt;/p&gt;

&lt;p&gt;Let's use the following variable as an example: &lt;code&gt;x="a.b.c"&lt;/code&gt;. Here is a list of the most often used parameter expansions, according to us:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stripping. Use-case: get a file extension or remove a file extension.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${x%.*} ≡ a.b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${x%%.*} ≡ a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${x#*.} ≡ b.c&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${x##*.} ≡ c&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;String replacement. 

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;${x/./\!} ≡ a!b.c&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;${x//./\!} ≡ a!b!c&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Array enumeration with &lt;code&gt;IFS&lt;/code&gt; and &lt;code&gt;[@]&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IFS="."; for v in ${x[@]}; do echo -n "($v)"; done ≡ (a)(b)(c)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also construct arrays with a "compound assignment":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
x=(a b c)
for v in ${x[@]}; do 
    echo -n "($v)"
done

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

&lt;/div&gt;



&lt;p&gt;IFS manipulation is not normally needed. If you're changing the splitting context, you should see if there is another way. You might be falling victim to the &lt;a href="https://mywiki.wooledge.org/XyProblem" rel="noopener noreferrer"&gt;XY problem&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;This tutorial should provide good-enough techniques to quickly and effectively implement shell scripts that do what you want them to. Quote your variables, fail fast, make backups to recover from destructive changes, don't use too many "advanced features" since they are error-prone, and good luck!&lt;/p&gt;

&lt;p&gt;We leave you with some shell scripts we wrote that push the boundaries of what shell should be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/manpages/usr-local-bin/blob/master/chess" rel="noopener noreferrer"&gt;A chess clock made in bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git.sr.ht/%7Ejonn/shmux/tree/master/item/shmux" rel="noopener noreferrer"&gt;A script I use daily: spawn or reattach to given project's &lt;code&gt;tmux&lt;/code&gt; session&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/manpages/issues-legacy/blob/master/issues#L5-L15" rel="noopener noreferrer"&gt;Auto-detect canonical path to the script and eval modules residing in &lt;code&gt;include/&lt;/code&gt; directory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/manpages/issues-legacy/blob/master/include/bye.sh" rel="noopener noreferrer"&gt;Terminate&lt;/a&gt; &lt;a href="https://github.com/manpages/issues-legacy/blob/master/issues#L3" rel="noopener noreferrer"&gt;process tree&lt;/a&gt;, &lt;a href="https://github.com/manpages/issues-legacy/blob/master/include/debug.sh" rel="noopener noreferrer"&gt;printing debug output&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there will be community interest, we will take some time to cover extensible shell scripting in Haskell with Turtle. As usual, reach out to us on &lt;a href="https://twitter.com/doma_dev" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or in the comments on &lt;a href="https://dev.to/doma"&gt;Dev.to&lt;/a&gt; or &lt;a href="https://doma-dev.medium.com/" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; mirrors.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Parser combinators in Rust</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Tue, 30 Mar 2021 20:57:59 +0000</pubDate>
      <link>https://dev.to/doma/parser-combinators-in-rust-1f2e</link>
      <guid>https://dev.to/doma/parser-combinators-in-rust-1f2e</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don't use regular expressions for parsing&lt;/li&gt;
&lt;li&gt;Parser combinators are a way to construct composable computations with higher-order functions

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;many1(digit1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alt((tag("hello"), tag("sveiki")))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pair(description, preceded(space0, tags))&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Parser combinators are easy to use to get results quickly&lt;/li&gt;
&lt;li&gt;They are sufficient for 99% of pragmatic uses, falling short only if your library's sole purpose is parsing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Role of parsing in computing
&lt;/h2&gt;

&lt;p&gt;Data processing is a pillar of computing. To run an algorithm, one must first build up some data structures in memory. The way to populate data structures is to get some raw data and load it into memory. Data scientists work with raw data, clean it and create well-formatted data sets. Programming language designers tokenise source code files and then parse those into abstract syntax trees. Web-scraper author navigates scraped HTML and extracts values of interest.&lt;/p&gt;

&lt;p&gt;Informally, each of these steps can be called "parsing". This post talks about how to do &lt;em&gt;complete, composable and correct parsing in anger&lt;/em&gt;. What do we mean by this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Parsing in anger&lt;/em&gt; considers the problem of data transformation pragmatically. A theoretically optimal solution is not required. Instead, the goal is to write a correct parser as quickly as possible.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Composable parsing&lt;/em&gt; means that the resulting parser may consist of "smaller" components. It can itself be later on used as a component in "bigger" parsers.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Complete parsing&lt;/em&gt; means that the input shall be consumed entirely. If the input can have any deviations or errors, its author shall encode them in the resulting parser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So how do we achieve it? Let's first talk about how to &lt;em&gt;not&lt;/em&gt; do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forget about regular expressions
&lt;/h2&gt;

&lt;p&gt;Thanks to the popularity of now perished Perl programming language, a whole generation of computer programmers was making &lt;a href="https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454"&gt;futile attempts to parse non-regular languages with regular expressions&lt;/a&gt;. Regular expressions are no more than encodings of finite-state automata.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8MOZVJZX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ctf.cdn.doma.dev/regex-is-automaton.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8MOZVJZX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ctf.cdn.doma.dev/regex-is-automaton.jpg" alt="An example finite state automaton, demonstrating /^(0*1+)+$/ JavaScript regex"&gt;&lt;/a&gt;&lt;em&gt;Items over arrows are characters of {0, 1} alphabet. Circles are states, q1 is "accepting state". Arrows denote state transitions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Non-deterministic finite-state automata can rather elegantly accept many non-trivial languages. Classical example is that no regular expression exists that accepts strings of form "ab", "aabb", "aaabbb", ... Equivalently, one can't solve the matching parentheses problem with a regular expression. The simplest stack machine is needed for that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2qqboiUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ctf.cdn.doma.dev/balanced-parentheses.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2qqboiUa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ctf.cdn.doma.dev/balanced-parentheses.jpg" alt="A sketch of a non-deterministic stack automaton that solves matching parentheses problem."&gt;&lt;/a&gt;&lt;em&gt;Stack automaton can be in several states at once. A state with no transitions "fizzles" on any input. &lt;code&gt;(@\*&lt;/code&gt; matches character '&lt;code&gt;(&lt;/code&gt;' with any stack state. &lt;code&gt;ε@ε&lt;/code&gt; matches instantaneously as the automaton gets to state p, but only if the stack is empty. &lt;a href="https://blackwells.co.uk/bookshop/product/Introduction-to-Automata-Theory-Languages-and-Computation-by-John-E-Hopcroft-author-Rajeev-Motwani-author-Jeffrey-D-Ullman-author/9781292039053"&gt;The best introductory book for those interested in formal languages&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thus, regular expressions are nowhere close to providing enough facilities to work with context-free grammars. But they may be sufficiently powerful to clean data or extract some values, so why are we saying you shouldn't use them ever? Practicality reasons!&lt;/p&gt;

&lt;p&gt;Let's take an example from some Regex Cookbook post (&lt;a href="https://medium.com/factory-mind/regex-cookbook-most-wanted-regex-aa721558c3c1"&gt;medium-paywalled link&lt;/a&gt;). This way we know it's an actual approach used in the industry. Here is one of the regular expressions author offers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
^(((h..ps?|f.p):\/\/)?(?:([\w\-\.])+(\[?\.\]?)([\w]){2,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\[?\.\]?){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)))*([\w\/+=%&amp;amp;_\.~?\-]*)$

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

&lt;/div&gt;



&lt;p&gt;Many can superficially understand what is going on here. This regex seemingly has something to do with links, but even when we resort to &lt;a href="https://regex101.com/r/6qUtv2/1/"&gt;automated explanation&lt;/a&gt;, things don't get much clearer. Well, according to the author, this regex is supposed to detect "defanged" URLs. Now let's see all ways in which it and any other sufficiently large regular expression fail.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It is wrong: it doesn't match &lt;code&gt;https://​ctflearn​.​com​/​&lt;/code&gt; (notice zero-width spaces).&lt;/li&gt;
&lt;li&gt;It requires external tokenising, so no plug-and-play: it doesn't match &lt;code&gt;␣https://ctflearn.com/&lt;/code&gt; (notice leading space).&lt;/li&gt;
&lt;li&gt;External tokenisation is specific to this expression: it doesn't match &lt;code&gt;https://ctflearn.com,&lt;/code&gt; (notice trailing comma).&lt;/li&gt;
&lt;li&gt;It's impossible to fix it: matching optional characters around each printable character would turn it from a large and poorly readable piece of code into a huge and completely unreadable one. Your brain wouldn't even be able to guess &lt;code&gt;h..ps&lt;/code&gt; and &lt;code&gt;f.p&lt;/code&gt; bits.&lt;/li&gt;
&lt;li&gt;It can't be used to extract values. Regexps don't "parse data into data structures". Rather they accept or decline strings. Thus, additional post-processing is required to make use of their output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Regular expressions have intrinsic problems. To us, it means that only short expressions should be used. The author uses them exclusively with &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, and &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These days, gladly, a better parsing methodology becomes mainstream with working libraries in all the popular languages. As you can guess from the title, it's called "parser combinators".&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-step guide to composable parsing
&lt;/h2&gt;

&lt;p&gt;In the spirit of our previous blogs, let's solve some practical task. Consider you have to write an interactive TODO application, the pinnacle of practicality. It specifies the following commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;add ${some word}* ${some #hashtag}*&lt;/code&gt; (appends item ID)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;done ${some item ID}&lt;/code&gt; (marks entry at item ID as resolved)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search ${some word or some #hashtag}+&lt;/code&gt; (searches across entries, returns a list of matching item IDs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's first define how will we represent parsed data, omitting the boring bits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
pub enum Entry {
    Done (Index),
    Add (Description, Vec&amp;lt;Tag&amp;gt;),
    Search (SearchParams),
}

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

&lt;/div&gt;



&lt;p&gt;Now let's use the &lt;code&gt;nom&lt;/code&gt; library to enjoy expressive and declarative parsing. It has or used to have macro API and function API. Since in v5 of the library macro API was very glitchy, we shall use function API, which we have tested with v6.&lt;/p&gt;

&lt;p&gt;We will be parsing the commands line by line. Begin with &lt;em&gt;declaring&lt;/em&gt; the top-level parse for a line and meet your first parser combinator: &lt;code&gt;alt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
pub fn command(input: &amp;amp;str) 
-&amp;gt; IResult&amp;lt;&amp;amp;str, Entry&amp;gt; { /* A */
    alt((done, add, search))(input) /* B */
}

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

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;(A)&lt;/code&gt; is declared that our function &lt;code&gt;command&lt;/code&gt; is a parser.&lt;a href="https://docs.rs/nom/6.1.2/nom/type.IResult.html"&gt;&lt;code&gt;IResult&lt;/code&gt;&lt;/a&gt; captures parsed type (in our case, &lt;code&gt;str&amp;amp;&lt;/code&gt;) and output data structure (in our case, &lt;code&gt;Entry&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;(B)&lt;/code&gt; we combine three parsers: &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;done&lt;/code&gt;, and &lt;code&gt;search&lt;/code&gt; with &lt;a href="https://docs.rs/nom/6.1.2/nom/branch/fn.alt.html"&gt;&lt;code&gt;nom::branch::alt&lt;/code&gt;&lt;/a&gt; combinator. It attempts to apply each of these parsers starting from the leftmost until one succeeds.&lt;/p&gt;

&lt;p&gt;Now, let's have a look at the simplest parser out of the three:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn done(input: &amp;amp;str) -&amp;gt; IResult&amp;lt;&amp;amp;str, Entry&amp;gt; {
    let (rest, value) = preceded( /* A */
        pair(tag("done"), ws), /* B */
        many1(digit1) /* C */
    )(input)?; 
    Ok((
      rest,
      Entry::Done( /* D */
        Index::new( vec_to_u64(value) )
      ) 
    ))
}

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

&lt;/div&gt;



&lt;p&gt;The first combinator we see straight away is &lt;code&gt;preceded&lt;/code&gt;. It forgets parse &lt;code&gt;(B)&lt;/code&gt; and keeps only the output of &lt;code&gt;(C)&lt;/code&gt;.&lt;code&gt;(B)&lt;/code&gt; still will consume input, however! Generally speaking, it &lt;em&gt;combines&lt;/em&gt; two computations into a composition that runs both of them, returning what the second one returns. It is not the same as just running them in a sequence because here we &lt;em&gt;build up a computation&lt;/em&gt;, but we will run it later on!&lt;/p&gt;

&lt;p&gt;Interestingly, if we were writing Haskell we wouldn't find "preceded" combinator in our &lt;a href="https://markkarpov.com/tutorial/megaparsec.html"&gt;parser library&lt;/a&gt;. The reason is that what we described in the previous paragraph is called "right applicative arrow", or, as was coined during Ben Clifford's &lt;a href="https://www.youtube.com/watch?v=r_Enynu_TV0"&gt;wonderful talk&lt;/a&gt; "right &lt;em&gt;sparrow&lt;/em&gt;":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
λ&amp;gt; :t (*&amp;gt;)
(*&amp;gt;) :: Applicative f =&amp;gt; f a -&amp;gt; f b -&amp;gt; f b

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

&lt;/div&gt;



&lt;p&gt;The other two combinators are pretty self-explanatory.&lt;code&gt;pair&lt;/code&gt; combines parsers into a sequence, with the &lt;code&gt;ws&lt;/code&gt; parser being a parser that consumes single whitespace. Here is a naive definition of &lt;code&gt;ws&lt;/code&gt;: &lt;code&gt;one_of(" \t")&lt;/code&gt;.&lt;code&gt;many1&lt;/code&gt; repeats a &lt;code&gt;digit1&lt;/code&gt; parse at least one time to succeed. &lt;code&gt;digit1&lt;/code&gt; is implemented in &lt;code&gt;nom&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Now let's solidify the understanding of how to make sure that our parsers can be used by others.&lt;/p&gt;

&lt;p&gt;We have already discussed that to achieve that, we need to return &lt;code&gt;IResult&lt;/code&gt;. Now it's time to remember that it's still a "Result" type, so its constructors are still &lt;code&gt;Err&lt;/code&gt; and &lt;code&gt;Ok&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Err&lt;/code&gt; variant of Result is constructed via the &lt;code&gt;?&lt;/code&gt; modifier, that passes any potential error arising in parse &lt;code&gt;(A)&lt;/code&gt; through.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ok&lt;/code&gt; variant of Result is constructed in &lt;code&gt;(D)&lt;/code&gt; by transforming &lt;code&gt;many1&lt;/code&gt; output (which is a vector of digits) into an unsigned 64-bit integer. It's done with &lt;code&gt;vec_to_u64&lt;/code&gt; function, which is omitted for brevity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The shape of &lt;code&gt;Ok&lt;/code&gt; value for &lt;code&gt;IResult&amp;lt;in, out&amp;gt;&lt;/code&gt; is &lt;code&gt;Ok((rest: in, value: out))&lt;/code&gt;. Here &lt;code&gt;rest&lt;/code&gt; is the remaining input to be parsed, and &lt;code&gt;value&lt;/code&gt; is the output result of the parser. You can see that &lt;code&gt;preceded&lt;/code&gt; parse in &lt;code&gt;(A)&lt;/code&gt; followed the very same pattern.&lt;/p&gt;

&lt;p&gt;Here are more advanced parsers, that should solidify your intuition about how to use parser combinators in anger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn add(input: &amp;amp;str) -&amp;gt; IResult&amp;lt;&amp;amp;str, Entry&amp;gt; {    
  let (rest, (d, ts)) = preceded( /* B */
    pair(tag("add"), ws),                     
    pair(description, preceded(space0, tags)) /* A */
  )(input)?;
  Ok( (
    rest,
    Entry::Add( Description::new(&amp;amp;d), ts )
  ) )
}

fn search(input: &amp;amp;str) -&amp;gt; IResult&amp;lt;&amp;amp;str, Entry&amp;gt; {
  let (rest, mash) = preceded(
    pair(tag("search"), ws),
    separated_list(
      tag(" "),
      alt((tag_contents, search_word)) /* C */
    )
  )(input)?;
  Ok((rest, mash_to_entry(mash)))
}

fn mash_to_entry(mash: Vec&amp;lt;SearchWordOrTag&amp;gt;) -&amp;gt; Entry /* D */
{ /* ... */ }

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

&lt;/div&gt;



&lt;p&gt;Parsing with combinators is so self-descriptive, it's hard to find things that need to be clarified, but here are a couple of highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeat &lt;code&gt;preceded&lt;/code&gt; to focus on the data you need to parse out, see &lt;code&gt;(A)&lt;/code&gt; and binding in &lt;code&gt;(B)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sometimes, you have to parse heterogeneous lists of things. The best way to do that in our experience is to create a separate data type to enclose this heterogeneity (&lt;code&gt;SearchWordOrTag&lt;/code&gt;, in our case) and then use &lt;code&gt;separated_list&lt;/code&gt; parser over &lt;code&gt;alt&lt;/code&gt; of options, like in &lt;code&gt;(C)&lt;/code&gt;. Finally, when you have a vector of matches, you can fold it into a neater data structure as needed by using a conversion function (see &lt;code&gt;(D)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This should be enough guidance for you to start getting comfortable with this amazing combinator-based parsing methodology. Here are some parting thoughts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay close attention to whitespaces, which can be a little tricky, especially since we're not aware of the automatic tokenisation option in nom.&lt;/li&gt;
&lt;li&gt;Take a look at &lt;a href="https://github.com/Geal/nom/blob/master/doc/choosing_a_combinator.md"&gt;choosing a combinator&lt;/a&gt; documentation page for the version of nom you are using (NB! entries in this table are pointing to macro versions of combinators rather than function versions).&lt;/li&gt;
&lt;li&gt;If you so choose, you can check out &lt;a href="https://git.sr.ht/%7Ejonn/todo-rs-public/tree/main/item/src/parser.rs"&gt;code truly written in anger&lt;/a&gt;, which inspired the snippets in this blog post. The code is authored by Chris Höppner and Jonn Mostovoy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If parsing is not your product or the main purpose of your library, odds are, parser combinators shall be sufficiently expressive and sufficiently performant for your tasks. We hope you liked this post and happy parsing!&lt;/p&gt;

&lt;p&gt;If you have any questions, you can reach out to &lt;a href="https://twitter.com/podmostom"&gt;Jonn&lt;/a&gt; and &lt;a href="https://twitter.com/polastasule"&gt;Pola&lt;/a&gt; directly. Start the conversation in the comments of the mirrors of this article on &lt;a href="https://dev.to/doma/"&gt;Dev.to&lt;/a&gt; and &lt;a href="https://doma-dev.medium.com/"&gt;Medium&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>rust</category>
      <category>haskell</category>
    </item>
    <item>
      <title>Pattern matching in Rust and other imperative languages</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Thu, 18 Mar 2021 07:28:17 +0000</pubDate>
      <link>https://dev.to/doma/pattern-matching-in-rust-and-other-imperative-languages-3e7b</link>
      <guid>https://dev.to/doma/pattern-matching-in-rust-and-other-imperative-languages-3e7b</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rust is an imperative language that has the most pattern-related language facilities

&lt;ul&gt;
&lt;li&gt;Has both shallow destructuring and deep destructuring&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;if let&lt;/code&gt; matching form can be utilised to alleviate the lack only multiple-head functions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;JavaScript has a lot of pattern-related language features

&lt;ul&gt;
&lt;li&gt;Position-based destructuring for arrays and key-based for objects&lt;/li&gt;
&lt;li&gt;Rest parameters, supporting destructuring&lt;/li&gt;
&lt;li&gt;Shallow-copy spread operator&lt;/li&gt;
&lt;li&gt;With support from Microsoft, Facebook and NPM, proper pattern-matching in JS is inevitable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Python has the weakest support for pattern-related facilities

&lt;ul&gt;
&lt;li&gt;Language support for pattern-matching is included in alpha (edit thanks to reddit)&lt;/li&gt;
&lt;li&gt;Packing/unpacking&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;C++ has powerful libraries for pattern matching. Language support is likely in C++23&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;All the time, ideas and approaches sift into the world of conventional programming languages world from the programming language theory research and functional programming world. Even Excel has lambdas now!&lt;/p&gt;

&lt;p&gt;In this post, we shall cover pattern matching in various imperative programming languages. We shall help you adopt pattern matching techniques to boost the expressiveness and conciseness of your code.&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%2Fctf.cdn.doma.dev%2Flinked%2Fvisitor-cpp-pattern-matching.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%2Fctf.cdn.doma.dev%2Flinked%2Fvisitor-cpp-pattern-matching.png" alt="Example of pattern matching techniques being more optimal programming method from the latest C++ pattern matching proposal"&gt;&lt;/a&gt;&lt;em&gt;An example from a C++ evolution proposal.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern matching in Rust
&lt;/h2&gt;

&lt;p&gt;Rust has the most advanced and well-designed pattern system among all imperative languages. Part of it, of course, can be attributed to the fact that developers of Rust had the luxury of building a language from the ground up. But most significantly, it stems from the rigour and culture of design and development.&lt;/p&gt;

&lt;p&gt;Pattern matching facilities in Rust language are almost as rich as in its older functional brother Haskell. To learn about them along with us, first, consider the following task (inspired by a real-life use-case):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Explore a non-strictly-structured JSON object where keys are species and values are sets of animals of these species.&lt;/p&gt;

&lt;p&gt;If an animal's coat is fur or feathers, it's &lt;code&gt;Cute&lt;/code&gt;, otherwise it's &lt;code&gt;Weird&lt;/code&gt;. If a species is "aye-aye", it's &lt;code&gt;Endangered&lt;/code&gt;. There may be new criteria discovered later on that change categorisation of a particular animal or species.&lt;/p&gt;

&lt;p&gt;Categorise animals with distinct &lt;code&gt;name&lt;/code&gt;s found in the given data set!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's start with encoding the categories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#[derive(Hash, Debug, PartialEq, Eq, PartialOrd, Ord)] /* A */
pub enum Category {
  Cute,
  Weird,
  Endangered,
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;(A)&lt;/code&gt; makes sure that Rust will order values from top to bottom, so that &lt;code&gt;Cute &amp;lt; Weird &amp;lt; Endangered&lt;/code&gt;. This ordering will be important later on.&lt;/p&gt;

&lt;p&gt;Now to encode the rules from the task. Since our JSON is unstructured, we can't rely on any property existing, so we can't safely &lt;code&gt;unwrap&lt;/code&gt; or reliably coerce JSON to some data Rust data structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn cat_species(v: &amp;amp;str) -&amp;gt; Category {
  match v {
    "aye-aye" =&amp;gt; Category::Endangered, /* A */
    _ =&amp;gt; Category::Cute, /* B */
  }
}

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

&lt;/div&gt;



&lt;p&gt;Our first &lt;code&gt;match&lt;/code&gt;! How exciting! This match is equivalent to switching over contents of variable &lt;code&gt;v&lt;/code&gt;, of course. However, it offers more flexibility later on. With the power of destructuring, we can match complex structures, not just single variables.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(A)&lt;/code&gt; shows how to match a literal value, &lt;code&gt;(B)&lt;/code&gt; shows the "catch-all" clause. This pattern match reads &lt;em&gt;species named "aye-aye" is endangered, other species are cute&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now let's have a look at how to write something more interesting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn cat_animal_first_attempt(v: &amp;amp;Value) -&amp;gt; Category {
  match v["coat"].as_str() {
    Some("fur") | Some("feathers") =&amp;gt; Category::Cute,
    _ =&amp;gt; Category::Weird,
  }
}

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

&lt;/div&gt;



&lt;p&gt;The rule of cuteness is satisfied, no unwrapping used. There are also no &lt;em&gt;explicit checks&lt;/em&gt; if the value has Some contents or it has None! This listing confidently states: &lt;em&gt;animals with a fur coat or with a feather coat are cute, others are weird&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But is this implementation good enough? One can check by considering a rule getting added, just as requirements warned us:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Animals that have the albino mutation are &lt;code&gt;Endangered&lt;/code&gt;. Otherwise, previous rules apply.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn cat_animal_first_attempt_1(v: &amp;amp;Value) -&amp;gt; Category {
  let cat = match v["coat"].as_str() { /* A */
    Some("fur") | Some("feathers") =&amp;gt; Category::Cute, /* B */
    _ =&amp;gt; Category::Weird,
  }
  match v["mutation"].as_str() {
    Some("albino") =&amp;gt; Category::Endangered,
    _ =&amp;gt; cat
  }
}

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

&lt;/div&gt;



&lt;p&gt;The snippet became bulky and boilerplate-y... We now have to thread some variable like in &lt;code&gt;(A)&lt;/code&gt;. We have to remember not to short-circuit computation in &lt;code&gt;(B)&lt;/code&gt; by adding a &lt;code&gt;return&lt;/code&gt; by accident. In case an additional rule pops up, we will need to decide between mutable &lt;code&gt;cat&lt;/code&gt; or versioned.&lt;/p&gt;

&lt;p&gt;So is this it? Pattern matching collapses the moment we need to capture some heterogeneous set of matches? Not quite. Let us introduce &lt;code&gt;if let&lt;/code&gt; statement, made just for this sort of challenge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
fn cat_animal(v: &amp;amp;Value) -&amp;gt; Category {
  if let Some("albino") = v["mutation"].as_str() {
    Category::Endangered
  } else if let Some("fur")
              | Some("feathers")
              = v["coat"].as_str() {
    Category::Cute
  } else {
    Category::Weird
  }
}

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

&lt;/div&gt;



&lt;p&gt;Now that's more like it. But wait, what does it mean? As with other pattern matches, left hand side is a pattern (for instance, &lt;code&gt;Some("albino")&lt;/code&gt;) and right hand side is value (for instance, &lt;code&gt;v["mutation"].as_str()&lt;/code&gt;). A branch under &lt;code&gt;if&lt;/code&gt; will get executed when and only when the LHS pattern shall match the RHS value.&lt;/p&gt;

&lt;p&gt;Pattern matching with &lt;code&gt;if let&lt;/code&gt; syntax makes us start with the most specific clause and fall through to less specific clauses in an unambiguous order, taking away excessive liberty and thus making the code less error-prone.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
pub fn categorise(
  data: HashMap&amp;lt;String, Vec&amp;lt;Value&amp;gt;&amp;gt;,
) -&amp;gt; HashMap&amp;lt;Category, Vec&amp;lt;String&amp;gt;&amp;gt; {
  let mut retval = HashMap::new();
  for (species, animals) in data {
    for animal in animals {

      if let Some(name) = (animal["name"].as_str()) { /* A */
        retval
          .entry(max(cat_species(species.as_str()),
                     cat_animal(&amp;amp;animal))) /* B */
          .or_insert(Vec::new()) /* C */
          .push(name.to_string())
      }

    }
  }
  retval
}

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

&lt;/div&gt;



&lt;p&gt;Now that we have categorisation functions, we can proceed to categorise our data set. If &lt;code&gt;(A)&lt;/code&gt; &lt;code&gt;if let&lt;/code&gt; match fails (current animal has no name supplied), we'll move to the next iteration. Not all the patterns have to have the catch-all arm.&lt;/p&gt;

&lt;p&gt;Otherwise, the variable &lt;code&gt;name&lt;/code&gt; will store the current animal's name and we will chain some functions from a handy &lt;code&gt;HashMap&lt;/code&gt; API. In &lt;code&gt;(B)&lt;/code&gt; we use the &lt;code&gt;Ord&lt;/code&gt; instance of &lt;code&gt;Category&lt;/code&gt; enum to determine the highest priority category between species-based categorisation and per-animal categorisation with &lt;code&gt;std::cmp::max&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Then &lt;code&gt;HashMap&lt;/code&gt;'s &lt;code&gt;entry&lt;/code&gt; returns the reference to the value under the category. If there is None, &lt;code&gt;or_insert&lt;/code&gt; in &lt;code&gt;(C)&lt;/code&gt; inserts an empty vector and returns a reference to it. Finally, we can push the name of the current animal to this vector, and it will appear in our mapping!&lt;/p&gt;

&lt;p&gt;We hope that this guide provides a reasonable introduction to pattern matching in Rust. See the full code of the example module &lt;a href="https://git.sr.ht/%7Epola/prismatic-vista/tree/b686d11c61ebe3971282fea89bffdec4bd4f8391/item/src/aaa_filter_all_printings.rs#L23" rel="noopener noreferrer"&gt;on sourcehut&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's finish the post with some information about pattern-related features of other popular imperative languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns in modern JavaScript
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const foldAndDump = (path, xs, ...cutoffs) =&amp;gt; {
  // snip
  for (c of cutoffs) {
    //snap
  }
}

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

&lt;/div&gt;



&lt;p&gt;An old feature of ECMAScript, the JS standard called "rest parameters" &lt;code&gt;...cutoffs&lt;/code&gt; will match arguments of a function beyond the second into an array called &lt;em&gt;cutoffs&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var rs = [];
for (let [printing, info] of
     Object.entries(allPrintingsJson['data']))
{
    rs.push({ ...info, "_pv_set": printing });
}

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

&lt;/div&gt;



&lt;p&gt;When the ellipsis isn't in the &lt;em&gt;argument list&lt;/em&gt;, it means that we're dealing with a newer feature called "spread syntax". &lt;code&gt;...info&lt;/code&gt; means "include &lt;code&gt;info&lt;/code&gt; object as is". Analogously, spread syntax can spread an enumerable object across arguments of a function call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const xs = [1,2,3];
console.log(sum(...xs));

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

&lt;/div&gt;



&lt;p&gt;Finally, there is unpacking, which is a pretty standard feature by now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt; [a,b] = [1,2]
[1, 2]
&amp;gt; {x,y} = {y: a, x: b}
{ y: 1, x: 2 }
&amp;gt; {k,l} = {y: a, x: b}
{ y: 1, x: 2 }
&amp;gt; [a,b,x,y,k,l]
[1, 2, 2, 1, undefined, undefined]

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Packing and unpacking in Python
&lt;/h2&gt;

&lt;p&gt;In modern Python, any iterable is unpackable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt;&amp;gt;&amp;gt; a, *b, c = {'hello': 'world', 4: 2, 'rest': True, False: False}
&amp;gt;&amp;gt;&amp;gt; a, b, c
('hello', [4, 'rest'], False)

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;*&lt;/code&gt; is analogous to JS's ellipsis (&lt;code&gt;...&lt;/code&gt;) operator. It can collect some "the rest of the values", but it can also work as a spread for iterables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt;&amp;gt;&amp;gt; print(*[1, 2, 3])
1 2 3

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

&lt;/div&gt;



&lt;p&gt;Conversely, in spirit of Python, there's a special case operator called "dictionary unpacking operator". It works very similar to spread operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;gt;&amp;gt;&amp;gt; print({'x': True, **{'y': False},** {'x': False, 'z': True}})
{'x': False, 'y': False, 'z': True}

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

&lt;/div&gt;



&lt;p&gt;Rightmost spread precedes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pack your bags: we're going pattern matching
&lt;/h2&gt;

&lt;p&gt;Every single language that is in active development is looking to adopt more and more features from functional languages, and pattern matching is no difference.&lt;/p&gt;

&lt;p&gt;We'll conclude this post with a list of languages that will adopt proper pattern matching, ranked by degree of certainty in adoption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern matching in C++
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pattern matching as seen in &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1371r3.pdf" rel="noopener noreferrer"&gt;this evolution document&lt;/a&gt; is likely to land in C++23&lt;/li&gt;
&lt;li&gt;While you wait, there's always &lt;a href="https://github.com/mpark/patterns" rel="noopener noreferrer"&gt;a library or two that does a reasonable job&lt;/a&gt; mimicking the new standard&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pattern matching in JavaScript
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tied for the first place in "the most likely to adopt proper pattern matching", JavaScript's standard called "ECMAScript", has &lt;a href="https://github.com/tc39/proposal-pattern-matching" rel="noopener noreferrer"&gt;this proposal&lt;/a&gt; backed by Microsoft, Facebook and NPM.&lt;/li&gt;
&lt;li&gt;The proposal is thoroughly reviewed and was moved to "stage 1", which puts the theoretical release of this feature in the 2023-2025 range.&lt;/li&gt;
&lt;li&gt;You can check our maths by inspecting &lt;code&gt;git log&lt;/code&gt;s in &lt;a href="https://github.com/tc39/proposals/blob/master/finished-proposals.md" rel="noopener noreferrer"&gt;completed proposals repository&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pattern matching in Python
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;There were different proposals throughout the history of Python, but &lt;a href="https://www.python.org/dev/peps/pep-0634/" rel="noopener noreferrer"&gt;PEP 634&lt;/a&gt; got implemented&lt;/li&gt;
&lt;li&gt;Alpha version of Python with "structural pattern matching" is available &lt;a href="https://www.python.org/downloads/release/python-3100a6/" rel="noopener noreferrer"&gt;since March 1st&lt;/a&gt; (thanks to reddit for pointing our attention to it)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The idea of pattern matching is to have a code execution branch based on patterns, instead of conditions. Instead of trying to encode &lt;em&gt;properties of values&lt;/em&gt; necessary for a code branch to get executed, programmers who use pattern-matching encode &lt;em&gt;how should values look like&lt;/em&gt; for it to happen. Thus, in imperative languages, pattern matching promises more expressive and declarative code compared to predicate statements such as &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;case&lt;/code&gt;, bar some corner cases.&lt;/p&gt;

&lt;p&gt;It might be a subtle difference, but once you get it, you add a very powerful way of expression to your arsenal.&lt;/p&gt;

&lt;p&gt;We find that understanding these concepts is akin to the understanding of declarative vs imperative programming paradigms. To those interested in the philosophy of the matter, we suggest finding a cosy evening to curl up with a cup of steaming drink and watch Kevlin Henney's "declarative thinking, declarative practice" talk:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube-nocookie.com/embed/nrVIlhtoE3Y" rel="noopener noreferrer"&gt;https://www.youtube-nocookie.com/embed/nrVIlhtoE3Y&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Kevlin Henney: Declarative Thinking, Declarative Practice. ACCU 2016. Non-tracking YouTube embed.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>rust</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The best hex editor that you have never heard of</title>
      <dc:creator>doma.dev</dc:creator>
      <pubDate>Wed, 10 Mar 2021 12:57:59 +0000</pubDate>
      <link>https://dev.to/doma/the-best-hex-editor-that-you-have-never-heard-of-5915</link>
      <guid>https://dev.to/doma/the-best-hex-editor-that-you-have-never-heard-of-5915</guid>
      <description>&lt;p&gt;From CSV to XML to JSON, humans sure love their structured data. Computers like it too. If you think about it, X86 assembly is not much more than a structured data format. So is true for ELF, dwarf, protobuf…&lt;/p&gt;

&lt;p&gt;PNGs, JPEGs and even MySQL database files are all structured binary formats. They can get corrupted, store hidden data or you might need to simply patch something inside without pulling heavy tools to work with a particular file format.&lt;/p&gt;

&lt;p&gt;To explore a binary file at a glance, we suggest using&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;hexdump -C to get classical side by side view of address space on the left, hex representation of bytes in the middle and best-effort to print binary as ASCII on the right&lt;/li&gt;
&lt;li&gt;xxd -b in case you prefer to look at binary representation instead of hexadecimal&lt;/li&gt;
&lt;li&gt;od -S4 or strings -n4 to automatically search for 4-byte long ASCII strings or longer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But what about editing?!&lt;/p&gt;

&lt;h3&gt;
  
  
  Hex editors are less-than-optimal tools
&lt;/h3&gt;

&lt;p&gt;There is no clear “winner” in terms of hex editors. The options are so abundant that most popular hex editors tend to be the worst in terms of stability and being able to handle large files. Besides, hex editors tend to be extremely byte-oriented, so for proper bitwise processing, you have to look elsewhere.&lt;/p&gt;

&lt;p&gt;Our choice is &lt;a href="https://sourceforge.net/projects/wxhexeditor/"&gt;wxHexEditor&lt;/a&gt;. Here’s an example of an attempt to unscramble some 7-bit ASCII with it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ux6oz4Ur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/900/1%2ALwujsueDF6dwkTHb6tu2Sw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ux6oz4Ur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn-images-1.medium.com/max/900/1%2ALwujsueDF6dwkTHb6tu2Sw.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see it’s easy to lose track of where we were, especially while trying to edit binary quickly with a hex editor.&lt;/p&gt;

&lt;p&gt;That’s why in this post we are providing a step-by-step guide on how to use GNU poke to do binary transformations!&lt;/p&gt;

&lt;h3&gt;
  
  
  GNU poke, step by step
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: WSL2-compatible Ubuntu LTS 20.04 Installation
&lt;/h4&gt;

&lt;p&gt;Sadly, right now it’s impossible to easily install main branch of poke without &lt;a href="https://nixos.org/guides/nix-pills/install-on-your-running-system.html"&gt;nix&lt;/a&gt;. Gladly, poke authors have recently &lt;a href="https://savannah.gnu.org/forum/forum.php?forum_id=9949"&gt;released v1&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install tcl-dev libgc-dev \
 libjson-c-dev libreadline-dev # (1)
wget https://ftp.gnu.org/gnu/poke/poke-1.0.tar.gz
tar xzvf ./poke-1.0.tar.gz
mkdir poke-1.0/build &amp;amp;&amp;amp; cd poke-1.0/build
../configure — prefix=”$(pwd)” # (2)
make
make install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(1): These are the libraries that were required for no-GUI installation on a reasonably fresh Ubuntu installation.&lt;/p&gt;

&lt;p&gt;(2): It’s very important to always override default prefix with project directory to not mess up your system. We symlink binaries we want to use to ~/.local/bin after installing them in the project directory.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Prepare output file
&lt;/h4&gt;

&lt;p&gt;Let’s say you need to work with a file called &lt;a href="https://ctf.cdn.doma.dev/file.in"&gt;file.in&lt;/a&gt;. If you change something while working in poke, the changes will be written to file.in right away, so you should prepare a sufficiently large file.out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat file.in &amp;gt; file.out; cat file.in &amp;gt;&amp;gt; file.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Describe input and output
&lt;/h4&gt;

&lt;p&gt;First check if your file format is already described in standard library, also&lt;br&gt;&lt;br&gt;
known as “pickles”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls -1 pickles/ | grep pk
argp.pk
bmp.pk
bpf.pk
btf-dump.pk
btf.pk
color.pk
ctf.pk
dwarf-common.pk
dwarf-frame.pk
dwarf-pubnames.pk
dwarf-types.pk
dwarf.pk
elf.pk
id3v1.pk
leb128.pk
mbr.pk
pktest.pk
rgb24.pk
time.pk
ustar.pk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, describe the structure of your input and your output (we don’t have a relevant pickle, so we don’t load anything):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type InAtom = struct {
  uint&amp;lt;7&amp;gt; host;
  bit guest;
};
type Input = InAtom[];

type Output = struct {
  byte[] hosts;
  bit[] guests;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Transform input to output
&lt;/h4&gt;

&lt;p&gt;It is possible to &lt;a href="https://doma.dev/blog/binary-processing-erlang-gnu-poke/#gnu-poke"&gt;map transformations of data to files straight away&lt;/a&gt;, but it’s also possible to do more conventional iterative conversions between Input and Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun solve = (Input xs) Output: {
  var resultHosts = byte[]();
  var resultGuests = bit[]();
  var bitsWrote = 0;
  var bytesWrote = 0;
  for (i in xs) {
    if (bitsWrote % 8 == 0) {
      resultGuests += [(0 as bit), i.guest];
      bitsWrote += 2;
    } else {
      resultGuests += [i.guest];
      bitsWrote += 1;
    }
    resultHosts += [(0 as bit):::i.host ];
    bytesWrote += 1;
  }
  return Output {
    hosts = resultHosts,
    guests = resultGuests
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Write output to a file
&lt;/h4&gt;

&lt;p&gt;Now let’s write something like “main” function, that will have the duty of reading file.in, processing it and producing file.out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun writeSolution = (string basename) bit:
{
  var fin = open(basename + ".in", IOS_F_READ | IOS_F_WRITE);
  var fout = open(basename + ".out", IOS_F_READ | IOS_F_WRITE);
  var input = Input @ fin : 0#B;
  var output = solve(input);
  printf("INPUT: %v\nOUTPUT: %v\n", input, output);

  / ***This doesn't work in 1.0 release for some reason:*** /
  /* Output @ fout : 0#B = output; */
  / ********************************************************* /

 **byte[] @ fout : 0#B = output.hosts;  
 bit[] @ fout : (output.hosts'size) = output.guests;**  
  close(fin);
  close(fout);
  return 0;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting bit here is mapping of variables onto IO space “fout”. When the mapping instruction is on the left hand side and a value is on the right hand side, it means that poke shall unwrap the contents of the value onto the IO space. In case of files it means that it shall write the contents of the value immediately.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6: Run it!
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat file.in &amp;gt; file.out &amp;amp;&amp;amp; cat file.in &amp;gt;&amp;gt; file.out &amp;amp;&amp;amp; ./poke/poke
     _____
 ---' __\_______
            ______ ) GNU poke 1.0
            __)
           __)
 ---. _______ )

...

For help, type ".help".
Type ".exit" to leave the program.
(poke) .load solve.poke
(poke) writeSolution ("file");
INPUT: [
  InAtom {host=100U,guest=1U},
  InAtom {host=111U,guest=1U},
  InAtom {host=109U,guest=0U},...,
  InAtom {host=95U,guest=0U},
  InAtom {host=95U,guest=1U}]
OUTPUT: Output {
  hosts=[100UB,111UB,...,95UB,95UB],
  guests=[0U,1U,1U,...,1U,0U,1U]}
(uint&amp;lt;1&amp;gt;) 0
(poke) .file file.out
(poke) dump
76543210 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789ABCDEF
00000000: 646f 6d61 7b77 3472 6d33 3537 5f77 336c doma{w4rm357_w3l
00000010: 636f 6d33 5f5f 5f74 305f 5f5f 7468 3135 com3___t0___th15
00000020: 5f5f 5f62 6c30 677d ef68 e5db 666b 6fbe ___bl0g }.h..fko.
00000030: ee66 d9c7 deda 66be bfbf e860 bfbf bfe9 .f....f....`....
00000040: d163 6bbf bebf .ck...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you got the secret message!&lt;/p&gt;

&lt;h3&gt;
  
  
  Now go poke something!
&lt;/h3&gt;

&lt;p&gt;This blog provides sufficient techniques for you to start editing binary data without worrying about your hex editor crashing.&lt;/p&gt;

&lt;p&gt;If you want to take a look at a functional programming approach, you’re welcome to read our blog over at doma.dev website, that covers &lt;a href="https://doma.dev/blog/binary-processing-erlang-gnu-poke/#binary-processing-with-erlang"&gt;using Erlang as a binary editor&lt;/a&gt; to make the same binary transformation.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
