<?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: Meeshkan</title>
    <description>The latest articles on DEV Community by Meeshkan (@meeshkan).</description>
    <link>https://dev.to/meeshkan</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%2Forganization%2Fprofile_image%2F1353%2Ff6c0a882-4631-4b0c-a9ad-f060d42545a6.png</url>
      <title>DEV Community: Meeshkan</title>
      <link>https://dev.to/meeshkan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meeshkan"/>
    <language>en</language>
    <item>
      <title>Reviving the Dhall API discussion</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Sun, 06 Sep 2020 16:29:28 +0000</pubDate>
      <link>https://dev.to/meeshkan/reviving-the-dhall-api-discussion-10k0</link>
      <guid>https://dev.to/meeshkan/reviving-the-dhall-api-discussion-10k0</guid>
      <description>&lt;p&gt;I've worked a lot with &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;REST&lt;/a&gt; and &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt; over the past year, and there some issues that crop up in both ways of building an API.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dense specs&lt;/strong&gt;: OpenAPI and GraphQL are fairly complex, and they both require a subtle understanding of how input arguments to an API effect the output. For example, to filter an 8base query, you have to understand how a quadruply-nested input argument will effect a specific subfield. Yikes!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Producer-first&lt;/strong&gt;: OpenAPI and GraphQL put control in the hands of API producers, which means that consumers are constrained in the way data can be viewed and aggregated by the JSON return type (OpenAPI) and structure of the type system (GraphQL).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clunky auth&lt;/strong&gt;: Authorization feels like a bolt-on in both OpenAPI and GraphQL. OpenAPI is a bit better in that different tokens can be used for different endpoints, but they both require &lt;em&gt;ad hoc&lt;/em&gt; fine-grained authorization solutions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom DSL&lt;/strong&gt;: Types from OpenAPI (ie the return type of a GET request) and GraphQL (ie an object type) cannot be used in another context without a lot of parsing and converting. Compare this to isomorphic TypeScript, where types can be standardized across entire projects through the use of libraries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These problems are not because OpenAPI or GraphQL are bad. It's just that modern software has complexities that neither spec was designed to handle.&lt;/p&gt;

&lt;p&gt;Tinkering with Dhall this weekend, I had the thought "What if Dhall could be the basis of a query language à la REST or GraphQL? Would this help solve some of the issues above?"&lt;/p&gt;

&lt;p&gt;Github did not disappoint - someone was already thiking of this a couple years ago and wrote an &lt;a href="https://github.com/ocharles/dhallql" rel="noopener noreferrer"&gt;initial design document&lt;/a&gt;. My spin on it is different, but the basic idea of using Dhall as a stand-in for GraphQL is the same. I'm curious to hear what people think!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Dhall
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dhall-lang.org" rel="noopener noreferrer"&gt;Dhall&lt;/a&gt; is a configuration language. It's basically JSON, but with variables, types, functions and the ability to include other files. It also has some built-in functions for basic tasks like folding lists.&lt;/p&gt;

&lt;p&gt;This is some dhall:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ name = "Mike", country = "Finland"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is some slightly more complicated Dhall.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let license = "Apache-2.0" in
{ name = "Mike", country = "Finland", license = license }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once variables are substituted and functions are evaluated, Dhall is output as plain old JSON or YAML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dhall for Web APIs
&lt;/h2&gt;

&lt;p&gt;The next sections of this article outline the basics of a Dhall-based API exchange using a pet store example. I'll then address how it solves the four problems I've identified above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service discovery
&lt;/h3&gt;

&lt;p&gt;The first step is to send a JWT (ie from Auth0) to a service discovery endpoint which returns a JSON object with two keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;schema&lt;/code&gt;, which shows the JSON schema that an API consumer can consume with the given token; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nonce&lt;/code&gt;, which must be sent along with the token to verify that the correct version of the schema is being served.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our example, the return value will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wjsmcpmpiyvpwqba"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/definitions/user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"definitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/definitions/pet"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pet"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"$ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#/definitions/user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dhall from the producer
&lt;/h3&gt;

&lt;p&gt;Now that the API consumer knows what information she or he can access with a given token, the server needs to be able to process requests for that information. This is where the Dhall comes in. The example presented below can be seen &lt;a href="https://gist.github.com/mikesol/8f685029361c13fcb44758480d82f651" rel="noopener noreferrer"&gt;in its entirety on this gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, let's import some functions we'll need a bit later on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let fold = https://prelude.dhall-lang.org/List/fold
let filter = https://prelude.dhall-lang.org/List/filter
let equal = https://prelude.dhall-lang.org/Natural/equal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data, as represented by an API producer, should be &lt;em&gt;flat&lt;/em&gt;. A single table with three columns will suffice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pointer&lt;/strong&gt;: A pointer to an underlying object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key&lt;/strong&gt;: A key on the object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt;: The value of the key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is my data model. It's a simple pet-store API, so there are three types of objects: &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Pet&lt;/code&gt; and &lt;code&gt;List&lt;/code&gt;. The keys of an object can be &lt;code&gt;Id&lt;/code&gt; (ie 42), &lt;code&gt;Type&lt;/code&gt; (ie &lt;code&gt;Pet&lt;/code&gt;), &lt;code&gt;Name&lt;/code&gt; (ie "Fluffy") etc. &lt;code&gt;Head&lt;/code&gt; and &lt;code&gt;Tail&lt;/code&gt; are a way to represent linked lists.&lt;/p&gt;

&lt;p&gt;Entries are integers, booleans, doubles, text, pointers to other objects called &lt;code&gt;Id_&lt;/code&gt;, a given &lt;code&gt;Type&lt;/code&gt;, and &lt;code&gt;Nil&lt;/code&gt; to signal an array terminates.&lt;/p&gt;

&lt;p&gt;Lastly, our &lt;code&gt;Db&lt;/code&gt; is a list of &lt;code&gt;Row&lt;/code&gt; objects that combine a pointer to an &lt;code&gt;Id&lt;/code&gt;, a key and a value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let Obj = &amp;lt;User | Pet | List&amp;gt;
let Key = &amp;lt;Id | Type | Name | Pets | Head | Tail&amp;gt;
let Entry = &amp;lt;Int_: Integer | Bool_: Bool | Double_: Double | Text_: Text | Id_: Natural | Type_: Obj | Nil&amp;gt;
let Row = { ptr: Natural, key: Key, val: Entry }
let Db = List Row
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Haskell and MongoDB had a baby, this'd be it. There is a notion of using a union - &lt;code&gt;Obj&lt;/code&gt; - to represent typed objects. At the same time, the way these things are mixed and matched is flexible.&lt;/p&gt;

&lt;p&gt;The last thing we do as an API producer is define how to pass this information to consumers. The signature of &lt;code&gt;Reader&lt;/code&gt; says "for whatever projection the consumer wants, if they provide a function from the db to the projection, I will provide that projection." We then feed the data to &lt;code&gt;ReaderImpl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that, in a live example, a Dhall-language binding in a given language (ie JavaScript, Python) would be used, and the data would be injected via that binding rather than hardcoding it in Dhall files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let Reader: Type = forall (Projection: Type)
  -&amp;gt; forall (ProjectionF: Db -&amp;gt; Projection)
  -&amp;gt; Projection

let ReaderImpl: Reader = \(Projection: Type)
  -&amp;gt; \(ProjectionF: Db -&amp;gt; Projection)
  -&amp;gt; ProjectionF [
    {ptr=0, key=Key.Id, val=Entry.Id_ 0},
    {ptr=0, key=Key.Type, val=Entry.Type_ Obj.User},
    {ptr=0, key=Key.Name, val=Entry.Text_ "Mike"},
    {ptr=0, key=Key.Pets, val=Entry.Id_ 1},
    {ptr=1, key=Key.Type, val=Entry.Type_ Obj.List},
    {ptr=1, key=Key.Head, val=Entry.Id_ 10},
    {ptr=1, key=Key.Tail, val=Entry.Nil},
    {ptr=10, key=Key.Id, val=Entry.Id_ 10},
    {ptr=10, key=Key.Type, val=Entry.Type_ Obj.Pet},
    {ptr=10, key=Key.Name, val=Entry.Text_ "Fluffy"}
  ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important convention to note in this setup is that the top-level object of the JSON schema is &lt;strong&gt;always&lt;/strong&gt; represented by the pointer &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, this code works for queries but not mutations. For mutations, you'd need a &lt;code&gt;Writer&lt;/code&gt; type with the following signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let Writer: Type = forall (Projection: Type)
  -&amp;gt; forall (TransformF: Db -&amp;gt; Db)
  -&amp;gt; forall (ProjectionF: Db -&amp;gt; Projection)
  -&amp;gt; Projection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transform function takes the Db and produces an altered version with whatever writes/deletes/updates one wants to do, and the projection function is the same as above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dhall from the consumer
&lt;/h3&gt;

&lt;p&gt;The consumer then fulfills her or his part of the contract by providing the projection function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let getName: (Db -&amp;gt; Natural -&amp;gt; Text) = \(db: Db)
  -&amp;gt; \(ptr: Natural)
  -&amp;gt; fold
     Row
     (filter
       Row
       (\(a: Row) -&amp;gt; equal a.ptr ptr)
       db)
      Text
      (\(a: Row) -&amp;gt; \(t: Text) -&amp;gt;
        merge {
          Id=t,
          Type=t,
          Name=merge {
            Int_=\(v: Integer) -&amp;gt; t,
            Bool_=\(v: Bool) -&amp;gt; t,
            Double_=\(v: Double) -&amp;gt; t,
            Text_=\(v: Text) -&amp;gt; v,
            Id_=\(v: Natural) -&amp;gt; t,
            Type_=\(v: Obj) -&amp;gt; t,
            Nil=t
          } a.val,
          Pets=t,
          Head=t,
          Tail=t
      } a.key) ""

let View = { name: Text }
in ReaderImpl
   View
   (\(db: Db) -&amp;gt; {
     name = getName db 0
   })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you &lt;a href="https://gist.github.com/mikesol/8f685029361c13fcb44758480d82f651" rel="noopener noreferrer"&gt;copy-and-paste the code in the gist&lt;/a&gt; and &lt;a href="https://dhall-lang.org" rel="noopener noreferrer"&gt;run it in the on-line dhall interpreter&lt;/a&gt;, you'll get &lt;code&gt;{"name":"Mike"}&lt;/code&gt; as the output JSON.&lt;/p&gt;

&lt;p&gt;NB that the &lt;code&gt;getName&lt;/code&gt; monstrosity above is in the grey-zone between producer and consumer. It is consumer side, but is boiler-plate-y enough to warrant a standardized implementation for all consumers. The great thing about Dhall is that these sort of functions can be factored into their own files.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this fixes the problems defined above
&lt;/h2&gt;

&lt;p&gt;Let's revisit the problems above one by one and see how this solution fixes them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spec
&lt;/h3&gt;

&lt;p&gt;The spec is JSON schema, pure and simple. It is more concise than OpenAPI, and it lacks having to deal with input parameters like GraphQL.&lt;/p&gt;

&lt;p&gt;It is up to the producer to ensure that the flat data structure fed to the projection function follows the JSON schema. Combing over it is then automatable with functions like &lt;code&gt;getName&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Power to the consumers
&lt;/h3&gt;

&lt;p&gt;The return type from the spec is &lt;em&gt;completely&lt;/em&gt; determined by the consumer. That's the line &lt;code&gt;let View = { name: Text }&lt;/code&gt; above. The JSON schema represents how the data is provided on the producer side, but it is entirely up to the consumer how they choose to aggregate it. In this case, I opted to leave off pets, going only for &lt;code&gt;{"name":"Mike"}&lt;/code&gt;. I didn't need to call the field &lt;code&gt;"name"&lt;/code&gt;, nor did I need to return &lt;code&gt;"Mike"&lt;/code&gt; unaltered. As consumers of the data, we aggregate it as we see fit.&lt;/p&gt;

&lt;p&gt;At the same time, the data can be infinitely deep, as we saw with the pets-to-owners recursive relationship in the JSON schema. This is why the types cannot be represented in anything other than a flat structure.&lt;/p&gt;

&lt;p&gt;The idea of consumers sending code to a server to execute and turn into a result may seem far-fetched, but Dhall is the &lt;em&gt;perfect&lt;/em&gt; language for this because it is ultra-secure (no IO possible) and has no recursion, so no infinite loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authorization
&lt;/h3&gt;

&lt;p&gt;In my opinon, the most important aspect of this design is that it gets authorization right. When the first handshake happens and the consumer receives a JSON schema based on their token, they know what &lt;em&gt;they&lt;/em&gt; will be allowed to see. They don't know anything about what anyone else can see or an underlying schema. The JSON encodes the entirety of their authorization permissions.&lt;/p&gt;

&lt;p&gt;It could be, for example, that a resource is both viewable (ie someone's name on a list of friends) and not viewable (ie the fact that that person is dating your ex) depending on where it shows up in the JSON schema. In this way, the same resource can have multiple different pointers, and similarly, the same pointer can be referenced recursively (pets-to-owners above), allowing for queries as deeply nested as the consumer wants. What stops a recursive loop is the fact that the consumer's query is not infinitely long, but we do not limit how deep they can nest their data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom DSL
&lt;/h3&gt;

&lt;p&gt;With Dhall, there's no custom DSL like GraphQL. There's just Dhall, and Dhall types can live across projects. Dhall was born for the internet, so including a type is as easy as pointing to its URL (as we saw with the imports of &lt;code&gt;fold&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;equal&lt;/code&gt; above).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conlcusion
&lt;/h2&gt;

&lt;p&gt;In this article, I presented four ways that I think modern API building suffers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The specs are too dense.&lt;/li&gt;
&lt;li&gt;The way data is queried and mutated is dictated by API producers.&lt;/li&gt;
&lt;li&gt;Authorization is broken.&lt;/li&gt;
&lt;li&gt;Custom DSLs require needless specialization.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I then presented a brief sketch for a Dhall-based web API that, in my opinion, solves these problems. I encourage you to paste the GitHub gist in the Dhall on-line evaluator to see how the whole thing ties together. Please let me know what you think!&lt;/p&gt;

</description>
      <category>dhall</category>
      <category>graphql</category>
      <category>rest</category>
      <category>api</category>
    </item>
    <item>
      <title>Four reasons that PureScript is your best choice to build a server in 2020</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Fri, 04 Sep 2020 12:49:46 +0000</pubDate>
      <link>https://dev.to/meeshkan/four-reasons-that-purescript-is-your-best-choice-to-build-a-server-in-2020-3137</link>
      <guid>https://dev.to/meeshkan/four-reasons-that-purescript-is-your-best-choice-to-build-a-server-in-2020-3137</guid>
      <description>&lt;p&gt;Today, on the #purescript channel of the functional programming Slack, I wrote "I think PureScript is the best choice for anyone building a server in 2020." To that, Peter Andersen asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Wow! What are the key things in your eyes that make it the best?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now if that's not an invitation to blog, I don't know what is!&lt;/p&gt;

&lt;p&gt;So, here are four reasons that PureScript is the best way to build a server in 2020. I'll tl;dr them here, but you should stick around for the bonus reason at the end as well!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hello world&lt;/li&gt;
&lt;li&gt;Portability&lt;/li&gt;
&lt;li&gt;Language&lt;/li&gt;
&lt;li&gt;Community&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hello world
&lt;/h2&gt;

&lt;p&gt;The time it takes to get a server up and running in PureScript is as fast as a &lt;code&gt;hello-world&lt;/code&gt; server in JavaScript and Python. At Meeshkan, we regularly have to push out a server for some random part of the stack, and my fingers can get in the PureScript+Payload groove as fast as Node+Express or Python+Flask.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;purescript spago xhr2
init
spago &lt;span class="nb"&gt;install &lt;/span&gt;payload
spago build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then mosy on over to &lt;code&gt;src/Main.purs&lt;/code&gt; and paste:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Prelude&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect.Aff&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Aff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Payload.Server&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Payload&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Payload.Spec&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Spec&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="kt"&gt;Spec&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
        &lt;span class="kt"&gt;GET&lt;/span&gt; &lt;span class="s"&gt;"/hello"&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Spec&lt;/span&gt;

&lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Aff&lt;/span&gt; &lt;span class="kt"&gt;Message&lt;/span&gt;
&lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Payload&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;launch&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spago run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try &lt;code&gt;curl http://localhost:3000/hello&lt;/code&gt;, get back &lt;code&gt;{"text": "world"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The package &lt;a href="https://pursuit.purescript.org/packages/purescript-payload" rel="noopener noreferrer"&gt;Payload&lt;/a&gt; is one of several ways to build a server in Purescript - there's also &lt;a href="https://pursuit.purescript.org/packages/purescript-hyper" rel="noopener noreferrer"&gt;Hyper&lt;/a&gt;. And there are libraries to work with GraphQL and OpenAPI as well.&lt;/p&gt;

&lt;p&gt;In the "just get stuff done" department, PureScript rivals languages like JavaScript, Python and Go. The next time you need to crank out a server, remember that PureScript is imminently crankable!&lt;/p&gt;

&lt;h2&gt;
  
  
  Portability
&lt;/h2&gt;

&lt;p&gt;PureScript is a front-end for multiple languages. It compiles to JavaScript, Go, Python, Erlang, Haskell, and C++, just to name a few. So the "write once, use everywhere" philosophy that made isomorphic Node+Browser development so popular is even &lt;em&gt;more&lt;/em&gt; powerful in PureScript. Furthermore, because PureScript is just transpiling, it can be deployed to environments like Heroku, Vercel or GCP by putting &lt;code&gt;spago run&lt;/code&gt; in your &lt;code&gt;package.json&lt;/code&gt; for the run command.&lt;/p&gt;

&lt;p&gt;If your server needs to access custom language features, like a ML model in Python or a killer library you can't live without in JavaScript, PureScript's foreign function interface allows for seamless interaction between PureScript and the target language. For example, if in PureScript we have:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="n"&gt;foreign&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you just need a &lt;code&gt;Main.js&lt;/code&gt; in the same folder:&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="c1"&gt;// Main.js&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And PureScript automatically links them up.&lt;/p&gt;

&lt;p&gt;The day you need to migrate your server from language X to language Y, you'll be glad you wrote most of it in PureScript. I recently had this experience with WebAudio - I wrote a proof of concept in PS-&amp;gt;JavaScript and did PS-&amp;gt;Wasm once I was ready to make it more performant at the expense of debugability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Language
&lt;/h2&gt;

&lt;p&gt;PureScript is in the same category of languages as Haskell, Idris, Agda and Coq. Because these languages lend themselves well to proving things, really smart people tend to flock to them, which means the discussion is usually pretty heady and newbs can get easily lost.&lt;/p&gt;

&lt;p&gt;However, this discussion masks the reality that functional languages are no more difficult to get started in than other ones. Imagine that you need to write a function that increments positive integers and returns some nullish value for anything less than 0. Compare an implementation in Python to the same in PureScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;posinc&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;return&lt;/span&gt; &lt;span class="bp"&gt;None&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;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;posinc&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kt"&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've shown these "Rosetta stone" examples before many-a-coder and have yet to find someone that feels one is inherently more difficult than the other.&lt;/p&gt;

&lt;p&gt;If I were a betting person, I'd bet that the type safety and clean, readable code that come with the Haskell family of languages will save you many-a-bug in production and cause you to never work with anything else. But alas, I don't bet. The only point I'll make here is that you don't need to have ten years of software development under your belt to grok PureScript. Getting up and running is no different than learning Python.&lt;/p&gt;

&lt;p&gt;...a quick aside to those of you who &lt;em&gt;are&lt;/em&gt; into FP and swear up and down by it. PureScript is not as full featured as Haskell, and doesn't have out-of-the-box dependent types like Idris/Agda, but it has a minimalistic feature set that allows you to do most of the stuff you'd actually want to do in a real-world app. Plus, it is really easy to deploy on Heroku, Vercel or AWS Lambda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community
&lt;/h2&gt;

&lt;p&gt;The PureScript community has an active, non-toxic &lt;a href="https://discourse.purescript.org/" rel="noopener noreferrer"&gt;Discourse&lt;/a&gt; and &lt;a href="https://functionalprogramming.slack.com" rel="noopener noreferrer"&gt;Slack&lt;/a&gt; populated by helpful people that answer each others' questions and share resources. Additionally, most libraries you'd ever need for a basic server have already been written with ample documentation on &lt;a href="https://pursuit.purescript.org/" rel="noopener noreferrer"&gt;Pursuit&lt;/a&gt;, and novel ideas are being explored all the time.&lt;/p&gt;

&lt;p&gt;A lot of PureScript coders also use &lt;a href="https://dhall-lang.org" rel="noopener noreferrer"&gt;dhall&lt;/a&gt; as an alternative to JSON for configuration. If you use &lt;code&gt;spago&lt;/code&gt; as I did above, you're using &lt;code&gt;dhall&lt;/code&gt; and you'll see &lt;code&gt;dhall&lt;/code&gt; files in your directory. For anyone that has ever been hit by a &lt;a href="https://news.ycombinator.com/item?id=23755843" rel="noopener noreferrer"&gt;configuration bug&lt;/a&gt;, you know the importance of getting config right early on in a project. PureScript+Dhall is an unbeatable combo in this regard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;I promised you a bonus, and here it is. While &lt;a href="https://meeshkan.com" rel="noopener noreferrer"&gt;Meeshkan&lt;/a&gt; is an equal-opportunity tester, we have additional bells and whistles in our service that we use if you provide us with certain assets like an OpenAPI spec or GraphQL schema. We also have tools that use the types of certain languages to create even more powerful tests, and PureScript is on the list. So by going with PureScript, your service will be more testable by Meeshkan. As our stack becomes more mature, we regularly open-source PureScript libraries to help folks build better servers and write more powerful tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;PureScript is still in early-adopter mode, and the community is tiny. I personally was reluctant to try it out at first because I didn't see the point over using Haskell. However, the velocity of development/deployment, the limited feature set one can wrap one's head around, and the portability won me over. The next time you're building a server, or even in your current server if it is in a language to which PureScript compiles, give PureScript a shot!&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>rest</category>
      <category>openapi</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Functional GraphQL 1 - Specs and typelevel parsing</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Fri, 04 Sep 2020 07:06:24 +0000</pubDate>
      <link>https://dev.to/meeshkan/functional-graphql-1-specs-and-typelevel-parsing-cgn</link>
      <guid>https://dev.to/meeshkan/functional-graphql-1-specs-and-typelevel-parsing-cgn</guid>
      <description>&lt;p&gt;One of the common points of friction in GraphQL-land is making sure resolvers are conformant to specs. There are three main strategies I've seen to do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runtime validation of IO like in &lt;a href="https://www.apollographql.com/" rel="noopener noreferrer"&gt;Apollo&lt;/a&gt; and &lt;a href="https://github.com/absinthe-graphql/absinthe" rel="noopener noreferrer"&gt;Absinthe&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Code generation, like &lt;a href="https://prisma.io" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; and &lt;a href="https://graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL code generator&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Deriving the schema from the resolvers or db, which is available in &lt;a href="https://github.com/hendrikniemann/purescript-graphql" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-graphql&lt;/code&gt;&lt;/a&gt; and underpins services like &lt;a href="https://8base.com" rel="noopener noreferrer"&gt;8base&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They all have their disadvantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runtime validation requires lots of testing and manual upkeep.&lt;/li&gt;
&lt;li&gt;Code generation requires constantly merging generated code and dealing with stubbed methods.&lt;/li&gt;
&lt;li&gt;Deriving the schema from the resolvers is my favorite so far, but IMO it puts the control in the wrong direction. A schema should be influenced equally by consumers, and putting too much control in the hands of producers makes development less fluid.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd like to talk about a different strategy: &lt;strong&gt;generation of resolver types&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The basic idea is that you have a schema, and the compiler uses the schema to generate the type of your resolver. That way, when the schema updates, the code no longer compiles, and getting the code to compile makes it schema-conformant.&lt;/p&gt;

&lt;p&gt;This strategy is possible in any strongly-typed language. For example, in TypeScript, &lt;a href="https://graphql-code-generator.com/" rel="noopener noreferrer"&gt;GraphQL code generator&lt;/a&gt; will generate a resolver type that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;schema&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;QueryResolvers&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;ContextType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ParentType&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;ResolversParentTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ResolversParentTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Resolver&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ResolversTypes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;ParentType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ContextType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Resolvers&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContextType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;QueryResolvers&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ContextType&lt;/span&gt;&lt;span class="o"&gt;&amp;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 already a vast improvement, but it still has a few issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Important parts of business logic cannot be known by a type generator. For example, if you want custom directives to influence authentication or need a more nuanced &lt;code&gt;context&lt;/code&gt;, a type generator becomes clunky.&lt;/li&gt;
&lt;li&gt;You need an extra layer of translation from input types to application-level types. For example, the String &lt;code&gt;me&lt;/code&gt; above may need to be a full-fledged &lt;code&gt;User&lt;/code&gt; object in the application.&lt;/li&gt;
&lt;li&gt;You lose the benefits of code generation in places where application logic is boring and repeatable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, while the generation of resolver types is helpful, we can do better. For the rest of this article, I'd like to talk about &lt;strong&gt;compile-time generation of resolver types&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is compile-time generation of types?
&lt;/h2&gt;

&lt;p&gt;Compile-time generation of types means using the compiler to generate one type from another type. While that many sound a bit strange, there's nothing about it that's conceptually different than generating one value from another value. In programming, for example, we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the type-level (switching to PureScript) this becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;ToString&lt;/span&gt; &lt;span class="n"&gt;a&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;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;toString&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ToString&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;toString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first example, we're guaranteed that any value that goes into &lt;code&gt;toString&lt;/code&gt; will come out as a &lt;code&gt;string&lt;/code&gt; on the other end. In the second example, we're guaranteed that any type that goes into &lt;code&gt;ToString&lt;/code&gt; will come out as &lt;code&gt;String&lt;/code&gt; on the other end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;forceString&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;ToString&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;forceString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;identity&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;forceString&lt;/span&gt; &lt;span class="s"&gt;"5"&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;toString&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've the same &lt;code&gt;toString&lt;/code&gt; function in JavaScript for free, and in addition, we've gotten a compile-time validator &lt;code&gt;forceString&lt;/code&gt;. To see why, let's look at what happens when you use &lt;code&gt;forceString&lt;/code&gt; with anything other than a string.&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%2Fi.ibb.co%2FxGtBDGm%2FScreenshot-from-2020-09-04-08-29-58.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%2Fi.ibb.co%2FxGtBDGm%2FScreenshot-from-2020-09-04-08-29-58.png" alt="Compiler 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we hover over it, you'll see that the compiler has "solved" what &lt;code&gt;forceString&lt;/code&gt; must take.&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%2Fi.ibb.co%2F0MtYSfQ%2FScreenshot-from-2020-09-04-08-30-01.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%2Fi.ibb.co%2F0MtYSfQ%2FScreenshot-from-2020-09-04-08-30-01.png" alt="Compiler 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;ToString&lt;/code&gt;, we've pulled a type out of thin air. If you look at &lt;code&gt;forceString&lt;/code&gt;, nowhere in the definition does it say &lt;code&gt;b&lt;/code&gt; must be a String. The compiler figures it out from the implementation of &lt;code&gt;ToString&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the same way, the compiler will figure out what &lt;em&gt;type&lt;/em&gt; our GraphQL resolver needs to be from our GraphQL spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  A slightly-more realistic example
&lt;/h2&gt;

&lt;p&gt;In the following example, we'll use &lt;a href="https://github.com/meeshkan/purescript-typelevel-parser" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-typelevel-parser&lt;/code&gt;&lt;/a&gt; to turn symbols into types. In PureScript, &lt;code&gt;Symbol&lt;/code&gt; is a kind. A &lt;strong&gt;kind&lt;/strong&gt; is just a family of types. The types that inhabit &lt;code&gt;kind Symbol&lt;/code&gt; are every unicode string. Thankfully, the binary of the PureScript compiler doesn't contain every unicode string (that'd be a pretty big compiler!). The compiler creates a type for each unicode String on-the-fly. So the type &lt;code&gt;"a"&lt;/code&gt; is of &lt;code&gt;kind Symbol&lt;/code&gt; just like the value &lt;code&gt;"a"&lt;/code&gt; is of &lt;code&gt;type String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of GraphQL, in this example, we'll use a spec called &lt;strong&gt;TypeQL&lt;/strong&gt;. This (fabricated) spec is a series of lowercase strings separated by &lt;code&gt;&amp;amp;&lt;/code&gt;. The general idea is that it defines keys that point to a type. Keys of what? Who knows! Perhaps a dictionary, perhaps a database - that's for us to decide when we implement the spec. What type do the keys point to? Who knows! Perhaps &lt;code&gt;Int&lt;/code&gt;, perhaps &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One example would be &lt;code&gt;gold&amp;amp;silver&amp;amp;bronze&lt;/code&gt; pointing to &lt;code&gt;Int&lt;/code&gt;, another would be &lt;code&gt;earth&amp;amp;wind&amp;amp;fire&lt;/code&gt; pointing to &lt;code&gt;Boolean&lt;/code&gt;. Like a GraphQL spec, our TypeQL spec doesn't &lt;em&gt;mean&lt;/em&gt; anything. It is just a container of information. Our program will give it meaning, just like a GraphQL resolver gives a spec meaning.&lt;/p&gt;

&lt;p&gt;An engineer has been tasked with taking a &lt;strong&gt;TypeQL&lt;/strong&gt; spec and creating a PureScript implementation that can work for any type. So, for example, if we get a spec &lt;code&gt;earth&amp;amp;wind&amp;amp;fire&lt;/code&gt;, then we want to be able to automatically generate a type &lt;code&gt;{ earth :: a, wind :: a, fire :: a }&lt;/code&gt;, where &lt;code&gt;a&lt;/code&gt; can be any type (&lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, etc).&lt;/p&gt;

&lt;p&gt;Let's start with some imports.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Prelude&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Prim.Row&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Cons&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Type.Data.Row&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RProxy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Type.Parser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;type&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!:!&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;ConsPositiveParserResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ListParser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;ListParserResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;Lowercase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;NilPositiveParserResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;SingletonMatcher&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;SingletonParserResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kt"&gt;SomeMatcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;kind&lt;/span&gt; &lt;span class="kt"&gt;ParserResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we define our spec. In this case, it will be &lt;code&gt;python&amp;amp;java&amp;amp;javascript&lt;/code&gt;. In the next article, this'll be a full blown GraphQL spec. Notice how &lt;code&gt;"python&amp;amp;java&amp;amp;javascript"&lt;/code&gt; is a Symbol, not a String, because of the identifier &lt;code&gt;type&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- our spec&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;OurSpec&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"python&amp;amp;java&amp;amp;javascript"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is defining a parser. In most cases, you never have to actually write a parser as it is done for you (ie Apollo parses GraphQL). The same will be true of our GraphQL parser in the next article, but I want to show you how it's done so that you can follow a full example&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;Key&lt;/span&gt;

&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Keys&lt;/span&gt;

&lt;span class="c1"&gt;-- here's our parser&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;KeyList&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ListParser&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;SomeMatcher&lt;/span&gt; &lt;span class="kt"&gt;Lowercase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!:!&lt;/span&gt; &lt;span class="kt"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SingletonMatcher'&lt;/span&gt; &lt;span class="s"&gt;"&amp;amp;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;Keys&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the primitives of &lt;code&gt;purescript-typelevel-parser&lt;/code&gt;, we define a list of lowercase values separated by the separator &lt;code&gt;&amp;amp;&lt;/code&gt; that accurately describes the TypeQL spec.&lt;/p&gt;

&lt;p&gt;Once we have a parser result, we need to define how it translates into a type that our application understands (continuing in GraphQL-speak, we need to define the type of our resolver). In this case, we will take the parser result and turn it into a row where every key points to something of type &lt;code&gt;i&lt;/code&gt;. For example, &lt;code&gt;foo&amp;amp;bar&amp;amp;baz&lt;/code&gt; with type &lt;code&gt;Int&lt;/code&gt; will turn into a type &lt;code&gt;{ foo :: Int, bar :: Int, baz :: Int }&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;TypeQLToRow&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ParserResult&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="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;nqlToRowNil&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="kt"&gt;TypeQLToRow&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ListParserResult&lt;/span&gt; &lt;span class="kt"&gt;NilPositiveParserResult&lt;/span&gt; &lt;span class="kt"&gt;Keys&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="n"&gt;res&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;nqlToRowCons&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;TypeQLToRow&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ListParserResult&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="kt"&gt;Keys&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cons&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;TypeQLToRow&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Success&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;ListParserResult&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;ConsPositiveParserResult&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SingletonParserResult&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="kt"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;y&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="kt"&gt;Keys&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="n"&gt;res&lt;/span&gt;

&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;SymbolToRow&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Symbol&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="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;symbolToTypeQLType&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;Parse&lt;/span&gt; &lt;span class="kt"&gt;KeyList&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;
  &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;TypeQLToRow&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;SymbolToRow&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can create our typelevel validator. The validator just passes through an object, but in doing so, validates at compile-time that the object conforms to our spec. For example, &lt;code&gt;{ python: 1, javascript: 2, java: 3 }&lt;/code&gt; conforms to our spec.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;intValidator&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="kt"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
  &lt;span class="kt"&gt;SymbolToRow&lt;/span&gt; &lt;span class="kt"&gt;OurSpec&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;Record&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="n"&gt;intValidator&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;a&lt;/span&gt;

&lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;javascript&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;intValidator&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's imagine that we now add a language (say purescript). Our spec becomes &lt;code&gt;python&amp;amp;java&amp;amp;javascript&amp;amp;purescript&lt;/code&gt;. What happens to &lt;code&gt;languages&lt;/code&gt;? Let's see!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;OurSpec&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"python&amp;amp;java&amp;amp;javascript&amp;amp;purescript"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we hoped, the compiler gets angry.&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%2Fi.ibb.co%2FG0z7kQy%2FScreenshot-from-2020-09-04-09-04-04.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%2Fi.ibb.co%2FG0z7kQy%2FScreenshot-from-2020-09-04-09-04-04.png" alt="Compiler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, because it deep down the PureScript compiler is nice, it gives us a helpful error message letting us know what we did wrong.&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%2Fi.ibb.co%2FJvRCwgN%2FScreenshot-from-2020-09-04-09-04-08.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%2Fi.ibb.co%2FJvRCwgN%2FScreenshot-from-2020-09-04-09-04-08.png" alt="Compiler love"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can fix it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;javascript&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;purescript&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;intValidator&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;javascript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;purescript&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion and next steps
&lt;/h2&gt;

&lt;p&gt;In this article, I've shown how typelevel-programming allows you to take a spec (ie TypeQL) and use it to generate a type. We use the type to create a validator that makes sure our code is always conformant with the spec. It's also allowed us to use custom business-logic (in this case, using &lt;code&gt;Int&lt;/code&gt; as the indexed type of our record).&lt;/p&gt;

&lt;p&gt;In the next article in this series, which will come out in mid-September 2020, I'll show how this strategy can be used to build type-safe GraphQL resolvers. In the meantime, if you're building a GraphQL API, you should sign up for &lt;a href="https://meeshkan.com" rel="noopener noreferrer"&gt;Meeshkan&lt;/a&gt;! We do automated testing of GraphQL APIs. Our novel approach combines functional programming and machine learning to execute thousands of tests against your GraphQL API and find mission-critical bugs and inconsistencies. Regisration is free, and don't hesitate to reach out - we'd love to learn more about what you're building!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>functional</category>
      <category>purescript</category>
    </item>
    <item>
      <title>When to start thinking about QA</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Mon, 31 Aug 2020 08:49:55 +0000</pubDate>
      <link>https://dev.to/meeshkan/when-to-start-thinking-about-qa-19bf</link>
      <guid>https://dev.to/meeshkan/when-to-start-thinking-about-qa-19bf</guid>
      <description>&lt;p&gt;At a conference recently, I heard someone ask the question "When's a good time to start thinking about QA?" The question was asked in earnest, but the speaker responded with a quick "Immediately!" and moved onto the next question. While "Immediately!" reflected the speaker's enthusiasm about quality assurance, it left the question-asker down in the dumps.&lt;/p&gt;

&lt;p&gt;Knowing when to think about QA is &lt;em&gt;really hard&lt;/em&gt;, and there's not that much good advice out there. A lot of blog posts, like the above-mentioned speaker, skirt the issue by saying things like "write more tests" or "use strong typing." Chances are, if you're Googling "When to start thinking about QA", these are not answers to your question. This article &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A couple definitions
&lt;/h2&gt;

&lt;p&gt;Once, when I was building an Android app, an angry supervisor asked us to "Stop throwing the app over the net to QA." I understood what the person meant, and I've heard this sort of critique a lot. The issue with the critique is that the most important part of the QA process &lt;em&gt;is&lt;/em&gt; throwing your app over the net. The reason you throw your app over the net is because, very soon, you will be throwing your app over an even bigger net called production.&lt;/p&gt;

&lt;p&gt;I like to use the analogy of the performing arts here: there are lots of rehearsals where you bring in someone from outside to look at your work. The last rehearsal (the dress rehearsal) is almost always this, but there are regular points in the development of a staged production where you'll bring in a trusted expert to give their opinion. You do this because, eventually, there will be hundreds and thousands of people forming their own opinion about your work, and it's important to make sure that your work represents your ideas. When you collaborate with a QA engineer, you're bringing someone in to watch a rehearsal.&lt;/p&gt;

&lt;p&gt;A lot of people worry that QA engineers will treat every rehearsal like the dress rehearsal, but this is not true. Great QA engineers know exactly what stage a project or feature is at and will give feedback that will help the project or feature &lt;em&gt;at that stage&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So to sum up, QA is a third-party viewpoint that gives you stage-appropriate technical feedback about your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The single most important step
&lt;/h2&gt;

&lt;p&gt;The most important step you can take, starting today, is kicking off a relationship with a QA professional or a company providing QA. This does not require purchasing or using a service - it just means introducing yourself.&lt;/p&gt;

&lt;p&gt;Great QA services (and we like to think we're building one!) know how to take it from here. Like a tailor or a doctor, they will start taking measures. By monitoring a codebase, a roadmap, and specs, a QA professional will focus on the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When are major releases planned?&lt;/li&gt;
&lt;li&gt;Are there any indicators that would predict increased development velocity at a given time?&lt;/li&gt;
&lt;li&gt;How often are there breaking changes to a service, and what are the precursors to these changes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions are asked in order to plan out when their help can be most impactful and necessary.&lt;/p&gt;

&lt;p&gt;At Meeshkan, we ask and answer these questions by testing code bases, creating specs, and building burn charts. The purpose of this is not to provide you with information (you're already overloaded!) but to answer even more important questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When will the team likely have time to digest test reports?&lt;/li&gt;
&lt;li&gt;Are there enough valuable indicators about quality to share them with the team?&lt;/li&gt;
&lt;li&gt;What is a five-alarm fire in the context of the team's business needs?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this means that, when you get a ping from us, you can trust us that it is important. Of course, we give you access to the entire trail that leads up to our decisions, and if you really want to, you can read over the tens of thousands of tests we run on your service. But our job is knowing &lt;em&gt;what&lt;/em&gt; to present to you, &lt;em&gt;when&lt;/em&gt; to present it, and &lt;em&gt;how&lt;/em&gt; it should be presented.&lt;/p&gt;

&lt;p&gt;So, introduce yourself! It will take a matter of minutes, and you'll be on the path to cultivating a long-term relationship that underpins great QA.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next step
&lt;/h2&gt;

&lt;p&gt;You've now won half the battle. Developing a relationship with a QA professional will aleviate a lot of stress because your trusted partner knows when to step in and when to get out of the way.&lt;/p&gt;

&lt;p&gt;The next step, and the other half of the battle, is what happens at the "rehearsal", to use the analogy from above. What are you hoping to get out of QA that you wouldn't get out of building a spec, writing a few tests, or using a great linter?&lt;/p&gt;

&lt;p&gt;QA is all about business outcomes. It puts itself in the place of the user, looks at the current state of the UX, and assesses if the "diff" between the current UX and the desired UX is on track. If a QA engineer crashes your app by pressing a button five times in rapid succession, they won't bring the crash to your attention unless it is linked to an underlying problem that can effect your bottom line.&lt;/p&gt;

&lt;p&gt;We see this all the time at Meeshkan. Our algorithms regularly crash servers by using very large numbers, negative pagination and other forms of exotic input. If you hear about this type of behavior from us, it is because we've linked the crashes to some underlying issue that we think is unsustainable. Otherwise, you won't hear from us because &lt;em&gt;it's ok if your app crashes in the wild&lt;/em&gt;. Don't let anyone tell you otherwise! What's not OK is for your business to consistently only ever return three out of twenty valid search results to a user. That's not a crash, but if search is a critical feature of your business, then that's a major problem. Great QA brings that to the fore.&lt;/p&gt;

&lt;p&gt;The difference between Meeshkan and traditional QA is that we do this automatically. There are several core benefits of automated QA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It explores a &lt;em&gt;lot&lt;/em&gt; of potential outcomes.&lt;/li&gt;
&lt;li&gt;It pools data from thousands of tests to recognize patterns and make the best possible predictions.&lt;/li&gt;
&lt;li&gt;It moves at the speed of your development by testing every change to source code.&lt;/li&gt;
&lt;li&gt;The price point makes it easy for small businesses to get started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automated QA is &lt;em&gt;not&lt;/em&gt; a replacement for manual QA. Someone will always need to give your app or service a spin in the wild. Sometimes your most enthusiastic users serve this role. But automated QA leads naturally to manual QA in several respects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It gives a tester a machine-built spec, which can act as a map of the service.&lt;/li&gt;
&lt;li&gt;It shows what parts of the app are the most trivial/predictable so that the manual tester can focus on the hard stuff.&lt;/li&gt;
&lt;li&gt;Like drivers in a self-driving car, manual testers provide a valuable source of confirmation to machine-built QA algorithms, creating a positive feedback loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An example
&lt;/h2&gt;

&lt;p&gt;Your business deploys a new service. Congrats! 🎊 Initially, all of the service's features are in your head, and you're able to do enough testing so that you confidence when you deploy.&lt;/p&gt;

&lt;p&gt;Soon, the service grows in complexity. You add authentication, you write to a database, and you start relying on other services. At a certain point, you begin to feel an uneasy feeling when you merge a branch to production. Why do you feel this way? You've tested the service as best you could, all the tests are passing, and still you fret about bad outcomes. It could be a logged out user accessing logged-in resources. It could be JSON parsing failure leading to serving a &lt;code&gt;404&lt;/code&gt;. But there's some form of psychological resistance to merging to production.&lt;/p&gt;

&lt;p&gt;The day you feel this is the day to kick off a conversation with a potential QA partner. If we're fortunate enough to earn your business, one of the first things we'll do is identify all of the points in your app that are most likely making you feel this way. For example, if you use some form of message passing like &lt;code&gt;spawn/register&lt;/code&gt; in an Erlang cluster or Google PubSub, we have a certain category of automated tests that apply to this type of setup.&lt;/p&gt;

&lt;p&gt;These tests don't just bombard the system with garbage input. For example, we will look to see if there are PubSub topics that are written to but never read. We will also try to find common mispellings of PubSub channels and potential deadlocks. You may get a report that says the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Channel &lt;code&gt;customerPaid&lt;/code&gt; expects input written to channel &lt;code&gt;customerRegistered&lt;/code&gt;, but &lt;code&gt;customerRegistered&lt;/code&gt; expects input to &lt;code&gt;customerPaid&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We may send you &lt;em&gt;only&lt;/em&gt; this in the report &lt;em&gt;even though&lt;/em&gt; your app is crashing in other places. This gets back to the main idea from above - our goal is not to taunt you with the 1,000 ways we made your service crash, but to distill our findings into the five things (maximum!) you need to know.&lt;/p&gt;

&lt;p&gt;PubSub is one of hundreds of places where automated QA moves the needle. At Meeshkan, we also look at CRUD operations, calls to third-party APIs, naming conventions, and many other indicators of quality that add up to create a rock-solid service.&lt;/p&gt;

&lt;p&gt;I've seen a lot of companies resist bringing in a QA professional because they're still experimenting with a novel idea and they're not sure if it's worth testing yet. I regularly hear folks say "Why bother bringing in QA if we may change the whole thing in a month anyway?" My answer is that one month is too long. Agile teams build upon successive hypotheses in a matter of days, and one way to speed up the process is having high-quality code early on. Meeshkan exists to provide value at exactly this stage. From the day you add Postgres or PubSub or OAuth2 to a service, our algorithms are able to discern if the use of a particular technology is idiomatic and viable.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to get started
&lt;/h2&gt;

&lt;p&gt;While we hope to be your trusted partner in automated QA, we realize that you have a choice in both automated an manual QA options. For manual QA and for writing your own tests in a Selenium-like style, we really like &lt;a href="https://www.rainforestqa.com/" rel="noopener noreferrer"&gt;Rainforest QA&lt;/a&gt;. For automated QA, and especially if you're just getting started, we recommend creating a free &lt;a href="https://app.meeshkan.com" rel="noopener noreferrer"&gt;Meeshkan account&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The purpose of this article, and why it is a bit longer than your average missive on the subject, is to avoid a kitch or cop-out answer to "When should I start thinking about QA?" It explores this question head on, addressing the purpose of QA, the benefits you can expect, and how to kick things off.&lt;/p&gt;

&lt;p&gt;As businesses increasingly find themselves pivoting to keep up with market tendencies, the major challenge of the next decade will not be making software that's built to last. It will be honing in on market signals faster than competitors. Your software is the &lt;em&gt;best&lt;/em&gt; signal detector there is, and modern quality assurance makes sure that what you are building will return as much signal and as little noise as possible. At Meeshkan, we accompany teams that build modern software. So what are you building?&lt;/p&gt;

</description>
      <category>qa</category>
      <category>testing</category>
      <category>graphql</category>
      <category>api</category>
    </item>
    <item>
      <title>Type-safe rationals in PureScript - why, what, and how</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Mon, 31 Aug 2020 08:44:35 +0000</pubDate>
      <link>https://dev.to/meeshkan/type-safe-rationals-in-purescript-why-what-and-how-3kj9</link>
      <guid>https://dev.to/meeshkan/type-safe-rationals-in-purescript-why-what-and-how-3kj9</guid>
      <description>&lt;p&gt;In the era of Corona, I've heard some amazing music projects recorded entirely remotely using technologies like virtual desktops and web audio. As a side project, I'm building an open-source web-based digital audio workstation that uses &lt;a href="https://purescript.org" rel="noopener noreferrer"&gt;PureScript&lt;/a&gt; in the browser as its scripting language. My hope is to facilitate remote audio collaboration and open up new creative possibilites for musicians all over the world.&lt;/p&gt;

&lt;p&gt;One of the biggest challenges in audio is parameter validation. There are so many numeric parameters and tracks in a modern audio project that it's really easy to saturate quickly, resulting in soul-crushing compression and limiting. Add more people to the equation, none of whom have the same mix in their head/ears, and it's a recipe for disaster. So one thing I wanted to get right from the outset was a representation of parameters where people could reason about acceptable ranges.&lt;/p&gt;

&lt;p&gt;A lot of user-facing parameters in audio are represented as rational numbers, most often between 0 and 1. Bearing this in mind, I set out to build a library that allows programmers to reason about numeric parameters their audio programs (or any programs) right from their IDE.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/mikesol/purescript-typelevel-rationals" rel="noopener noreferrer"&gt;purescript-typelevel-rationals&lt;/a&gt;. They allow you to keep track of flows of rational numbers to know exactly what the possible range of output values will be. I hope that it helps musicians make more subtle mixes. With time, I'll add features like trigonometric functions, natural logarithms, complex numbers, and other things that can be expressed at the type level.&lt;/p&gt;

&lt;p&gt;That's all well and good, but &lt;em&gt;what&lt;/em&gt; is a rational number expressed as a type? I'm glad you asked!&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-level programming
&lt;/h2&gt;

&lt;p&gt;Anyone that uses a strongly typed functional language works with the compiler to some extent as they write their code. Fingers tire, the brain starts to shut down, and at a certain point you think "ah, whatever, let the compiler do the hard work" as you press compile. There are IDE extensions for most languages that'll put these warnings in your editor so that you can tidy up right as you code.&lt;/p&gt;

&lt;p&gt;Type-level programming, for me, is a way to enhance this experience. It teaches the compiler to catch mistakes based on the types you define. For example, if you find a way to define &lt;code&gt;PositiveFloat&lt;/code&gt;, then the compiler can warn you or downright fail the build anytime the value dips into the negatives. For audio applications, this is really important, as a lot of plugins have wanky behavior with negative input.&lt;/p&gt;

&lt;h3&gt;
  
  
  My PureScript implementation
&lt;/h3&gt;

&lt;p&gt;To start, I define a number not as a value, but as a &lt;em&gt;constrained value&lt;/em&gt;. To the right of the colon is a constraint meaning &lt;code&gt;0 &amp;lt;= n &amp;lt; 1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Nt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Lt&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Lt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;oneHalf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asConstraintedRational&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Between0And1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will yield a value of &lt;code&gt;1/2&lt;/code&gt; with the following type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kt"&gt;Just&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;AndConstraint&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kt"&gt;NotConstraint&lt;/span&gt;
              &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;LessThanConstraint&lt;/span&gt; &lt;span class="kt"&gt;Zero&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;span class="kt"&gt;LessThanConstraint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PRational&lt;/span&gt; &lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="kt"&gt;P1&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;Because our constraint is between 0 and 1, the compiler does not know that it is &lt;code&gt;1/2&lt;/code&gt;, but it does know that it is in an initial acceptable range. Had we tried to do the following, we would have gotten &lt;code&gt;Nothing&lt;/code&gt; because &lt;code&gt;3/2&lt;/code&gt; is greater than &lt;code&gt;1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;
&lt;span class="n"&gt;oneHalf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asConstraintedRational&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="c1"&gt;-- Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Traditionally, this type of validation function is implemented so that it yields &lt;code&gt;Maybe Float&lt;/code&gt;. While that's all well and good, we lose tons of information by working with a blunt instrument like &lt;code&gt;Float&lt;/code&gt;. Our type above may be a bit verbose (we can stash it in a type variable to save room), but it communicates our intention exactly.&lt;/p&gt;

&lt;p&gt;Of course, a type with that wide of an ambitus only makes sense when you're not sure what the input will be, ie if you're reading from disk. If you know it's &lt;code&gt;1/2&lt;/code&gt;, just say it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;ExactlyOneHalf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;EqConstraint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;oneHalfPrecise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asConstraintedRational&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;ExactlyOneHalf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  invoke
&lt;/h3&gt;

&lt;p&gt;The next important bit is &lt;code&gt;invoke&lt;/code&gt;. It takes a function from &lt;code&gt;a -&amp;gt; c&lt;/code&gt;, where &lt;code&gt;a&lt;/code&gt; is a constrained rational, and transforms it into a function of type &lt;code&gt;b -&amp;gt; c&lt;/code&gt; if &lt;code&gt;b&lt;/code&gt;'s type is a sub-constraint of &lt;code&gt;a&lt;/code&gt;. For example, &lt;code&gt;0 &amp;lt;= n &amp;lt; 2&lt;/code&gt; is a sub-constraint of &lt;code&gt;-1 &amp;lt;= n &amp;lt; 2&lt;/code&gt; but not &lt;code&gt;-1 &amp;lt;= n &amp;lt; 1&lt;/code&gt;. The constraints and subconstraints can get as wild as you'd like, ie &lt;code&gt;(0 &amp;lt;= n &amp;lt; 2 &amp;amp; 4 &amp;lt;= n &amp;lt; -5) || n &amp;lt; -42&lt;/code&gt;. &lt;code&gt;purescript-typeleve-rationals&lt;/code&gt; figures it out.&lt;/p&gt;

&lt;p&gt;To use invoke, let's take the &lt;code&gt;oneHalfPrecise&lt;/code&gt; we defined above. Now, let's create a function that accepts any value between &lt;code&gt;0 &amp;amp; 1&lt;/code&gt; and returns &lt;code&gt;0.25&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;OneQuarter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;EqConstraint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P4&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;returnAQuarter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;OneQuarter&lt;/span&gt;
&lt;span class="n"&gt;returnAQuarter&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constConstrained&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;CRProxy&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;CRProxy&lt;/span&gt; &lt;span class="kt"&gt;OneQuarter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, &lt;code&gt;resolve&lt;/code&gt; resolves a constraint into a rational if it is a single value (ie &lt;code&gt;1/4&lt;/code&gt;) and &lt;code&gt;constConstrained&lt;/code&gt; converts it back to a constrained rational. To see how powerful resolve is, try to mess with it. For example, in my &lt;code&gt;IDE&lt;/code&gt;, I changed the &lt;code&gt;NotConstraint (LessThanConstraint (PRational P1 P4))&lt;/code&gt; to &lt;code&gt;NotConstraint (LessThanConstraint (PRational P1 P5))&lt;/code&gt;. That means that the value is between &lt;code&gt;1/5&lt;/code&gt; and &lt;code&gt;1/4&lt;/code&gt;, so we can no longer resolve it to a single value. Sure enough, the IDE gets angry at me. Thanks, PureScript compiler!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5r5jV6ET--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/QHYyP66/Screenshot-from-2020-08-27-16-04-15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5r5jV6ET--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/QHYyP66/Screenshot-from-2020-08-27-16-04-15.png" alt="red compiler invoke" width="640" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our function, let's invoke it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;myQuarterBack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoke&lt;/span&gt; &lt;span class="n"&gt;returnAQuarter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;oneHalfPrecise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neato, we get a quarter. But what if we tried to invoke it with something (gasp) outside of its proscribed range of &lt;code&gt;0 &amp;lt;= n &amp;lt; 1&lt;/code&gt;? Let's find out!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--339cFtmo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/m4K0Gnf/Screenshot-from-2020-08-27-17-31-57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--339cFtmo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ibb.co/m4K0Gnf/Screenshot-from-2020-08-27-17-31-57.png" alt="red compiler resolve" width="671" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow, that compiler is livid. As it should be! We've tried to invoke a function with a value (&lt;code&gt;3/2&lt;/code&gt;) outside of its domain (&lt;code&gt;1/2&lt;/code&gt;). Going back to audio, think of all those ears that will be spared from gratuitous clipping. Unless you're into Merzbow, in which case you can make a constraint that the volume should always be &lt;em&gt;over&lt;/em&gt; one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding numbers
&lt;/h3&gt;

&lt;p&gt;Lastly, let's see how &lt;code&gt;invoke&lt;/code&gt; allows us to specialize functions, like an adder, for specific input.&lt;/p&gt;

&lt;p&gt;First, we'll create an adder for numbers between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Gte0lt1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Nt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Lt&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Lt&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="kt"&gt;Gte0lt1&lt;/span&gt;

&lt;span class="n"&gt;zeroToOneAdder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;addConstrainedRationals&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
    &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRational&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="kt"&gt;InvokableRational&lt;/span&gt;
      &lt;span class="kt"&gt;Gte0lt1&lt;/span&gt;
      &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRational&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="kt"&gt;InvokableRational&lt;/span&gt;
        &lt;span class="kt"&gt;Gte0lt1&lt;/span&gt;
        &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRational&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="kt"&gt;AddConstraint&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="n"&gt;c&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;Now that that's done, we can create a specialized function called &lt;code&gt;addTwoHalves&lt;/code&gt; that &lt;em&gt;only&lt;/em&gt; accepts values that are &lt;code&gt;1/2&lt;/code&gt; and, consequentially, returns 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;EqConstraint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P1&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;IsOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;EqConstraint&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;P4&lt;/span&gt; &lt;span class="o"&gt;+/&lt;/span&gt; &lt;span class="kt"&gt;P4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;addTwoHalves&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
  &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="kt"&gt;IsOne&lt;/span&gt;
&lt;span class="n"&gt;addTwoHalves&lt;/span&gt; &lt;span class="n"&gt;i0&lt;/span&gt; &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;finalStep&lt;/span&gt;
  &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;curryFirstArg&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
    &lt;span class="kt"&gt;Between0And1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRational&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
      &lt;span class="kt"&gt;AddConstraint&lt;/span&gt;
        &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt;
        &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt;
        &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;curryFirstArg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoke&lt;/span&gt; &lt;span class="n"&gt;zeroToOneAdder&lt;/span&gt; &lt;span class="n"&gt;i0&lt;/span&gt;

  &lt;span class="n"&gt;finalStep&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;
    &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ConstrainedRational&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="kt"&gt;AddConstraint&lt;/span&gt;
      &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt;
      &lt;span class="kt"&gt;IsOneHalf&lt;/span&gt;
      &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="kt"&gt;ConstrainedRatioI&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
  &lt;span class="n"&gt;finalStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoke&lt;/span&gt; &lt;span class="n"&gt;curryFirstArg&lt;/span&gt; &lt;span class="n"&gt;i1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The amazing thing here is that, when you give the function a signature, the type of the return value &lt;em&gt;has&lt;/em&gt; to be &lt;code&gt;ConstrainedRatioI IsOne&lt;/code&gt;. Try it out yourself - if you put any other constrained rational as the return value, the program won't compile. That means that, just by solving type constraints supplied by &lt;code&gt;AddConstraint&lt;/code&gt;, the PureScript compiler is smart enough to follow two constrained values through the insides of our addition function and know what constrained is supposed to come out the other side.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;Type-level programming in PureScript is just straight-up programming, no more, no less. All of the things I'm about to show you (kinds, functional constraints, type classes etc) take a while to fully understand, but for the purpose of this blog, the most important thing to grok are the equivalencies in a hand-wavy way.&lt;/p&gt;

&lt;p&gt;In normal-land, this is how you'd define the Peano representation of the integers.&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;Peano&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In type-level programming, you do the same thing using kinds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;foreign&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;kind&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;span class="n"&gt;foreign&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;span class="n"&gt;foreign&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, onto functions. To define addition on the Peano integers, you can do (for example):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="kt"&gt;Zero&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;x&lt;/span&gt;
&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same thing in type classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;addZero&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;addSucc&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's see how we'd implement a series of functions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;
&lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;mul&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mul&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same thing in type classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Mul&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Peano&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;mulZero&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Mul&lt;/span&gt; &lt;span class="kt"&gt;Zero&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;mulSuc&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mul&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Add&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Succ&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information on what's going on under the hood, check out &lt;a href="https://blog.wuct.me/fun-with-typed-type-level-programming-in-purescript-5f8af42cfec5" rel="noopener noreferrer"&gt;this post&lt;/a&gt;, which is where I learned to do all this stuff.&lt;/p&gt;

&lt;p&gt;So that's it. When doing type-level programming in PureScript, you have access to recursive functions, pattern matching, and data constructors. What more does one need? If it weren't for that pesky varmant I/O, you could write your entire program just using types. But because my audio project will have I/O (ie a microphone and a speaker), you need some form of input validation and coersion to output. As we saw above, that's doable with &lt;code&gt;invoke&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Type-level programming in PureScript is lots of fun, and the community is implementing helpful things to make it easier all the time. After sprucing up this library a bit and adding more numeric features, I hope to get some killer WebAudio-API-music flowing through it!&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>functional</category>
    </item>
    <item>
      <title>Profunctors are everywhere!</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Mon, 31 Aug 2020 08:42:14 +0000</pubDate>
      <link>https://dev.to/meeshkan/profunctors-are-everywhere-27m4</link>
      <guid>https://dev.to/meeshkan/profunctors-are-everywhere-27m4</guid>
      <description>&lt;p&gt;Profunctors are a &lt;em&gt;really useful abstraction&lt;/em&gt;. It took me a while to understand what they are, but once I did, I found myself using them in contexts as diverse as digital signal processing, server building and data mining.&lt;/p&gt;

&lt;p&gt;In this article, I'd like to share the intuition I've built up about profunctors. The way I learned these things is by studying how profunctors can be used to create &lt;a href="https://medium.com/@gcanti/introduction-to-optics-lenses-and-prisms-3230e73bfcfe#:~:text=Optics%20are%20a%20very%20useful,values%20in%20a%20data%20type." rel="noopener noreferrer"&gt;optics&lt;/a&gt;. By the end of the article, I hope you'll see the value of using profunctors and optics in your day-to-day work!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's a profunctor?
&lt;/h2&gt;

&lt;p&gt;In short, a profunctor fulfills three criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has input and output.&lt;/li&gt;
&lt;li&gt;You can bolt on something to the "output" end to modify the output.&lt;/li&gt;
&lt;li&gt;You can bolt on something to the "input" end to convert input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this sounds like a &lt;strong&gt;function&lt;/strong&gt;, it's because functions are profunctors! Let's see how.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A function has input and output. In JavaScript, &lt;code&gt;(a) =&amp;gt; a * 3&lt;/code&gt; maps input, like &lt;code&gt;5&lt;/code&gt;, to output, like &lt;code&gt;15&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We can bolt something to the output. &lt;code&gt;(b) =&amp;gt; ((a) =&amp;gt; a * 3)(b) - 5&lt;/code&gt; takes our original function and, for the same input &lt;code&gt;5&lt;/code&gt;, now returns &lt;code&gt;10&lt;/code&gt; instead of &lt;code&gt;15&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We can convert input. &lt;code&gt;(b) =&amp;gt; ((a) =&amp;gt; a * 3)(b + 1)&lt;/code&gt; takes our original function and, for the same input &lt;code&gt;5&lt;/code&gt;, now returns &lt;code&gt;18&lt;/code&gt; instead of &lt;code&gt;15&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;(bonus) We can convert input &lt;em&gt;and&lt;/em&gt; modify output at the same time. &lt;code&gt;(b) =&amp;gt; ((a) =&amp;gt; a * 3)(b + 1) - 5&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profunctors are &lt;em&gt;not&lt;/em&gt; just functions. Profunctors are a &lt;em&gt;general way to conceive of IO&lt;/em&gt;. This is why I find them so useful. As programmers, we deal with IO on a micro-level (ie chaining functions) and a macro-level (ie chaining audio plugins) all the time.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.purescript.org" rel="noopener noreferrer"&gt;PureScript&lt;/a&gt;, the function that performs the operation above is called &lt;code&gt;dimap&lt;/code&gt; and it works like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="n"&gt;profunctor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;new_profunctor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The four JS examples above can be written in PureScript as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flip&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;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;flip&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the remainder of the article, we'll focus on one profunctor that I'll affectionately call "The Plus One Server". It takes a number and returns the number + 1. In JavaScript, &lt;code&gt;(a) =&amp;gt; a + 1&lt;/code&gt;. In Python &lt;code&gt;lambda a: a + 1&lt;/code&gt;. In &lt;a href="https://en.wikipedia.org/wiki/Brainfuck" rel="noopener noreferrer"&gt;Brainfuck&lt;/a&gt; &lt;code&gt;&amp;gt;+[-&amp;lt;+&amp;gt;]&amp;lt;&lt;/code&gt;. You get the idea.&lt;/p&gt;

&lt;p&gt;Let's say that we've written "The Plus One Server" (aka &lt;code&gt;((+) 1.0)&lt;/code&gt;) and we now learn that it needs to accept and return a string. The temptation may be to do something like this:&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;const&lt;/span&gt; &lt;span class="nx"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;original&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;span class="nf"&gt;modified&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3.1416&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "4.1416"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thinking profunctorially, we can do it like this in PureScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;
&lt;span class="n"&gt;modified&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- "4.1416"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;readFloat&lt;/code&gt; changes a string to a number, &lt;code&gt;show&lt;/code&gt; changes a number to a string, and &lt;code&gt;((+) 1)&lt;/code&gt; is my profunctor.&lt;/p&gt;

&lt;p&gt;The difference between the JS and PureScript versions is subtle but important. The first sends us on the path to spaghetti code, and the second leads to organizing things in a clean, maintainable way.&lt;/p&gt;

&lt;p&gt;To see why, imagine that the boss comes along and she says "Hey, coder person, your plus-one server needs to accept UTF8 byte strings and return byte strings." No prob, profunctors to the rescue!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;
&lt;span class="n"&gt;bossMadeMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;fromUTF8&lt;/span&gt; &lt;span class="n"&gt;toUTF8&lt;/span&gt; &lt;span class="n"&gt;modified&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the JS version, we'd have to constantly dip into the internals of the function to make changes, whereas here, we just bolt converters onto both ends and we're done with it.&lt;/p&gt;

&lt;p&gt;Let's now imagine that the boss, ever fickle, decides to keep the output format as &lt;code&gt;String&lt;/code&gt;. No problem!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;modified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt;
&lt;span class="n"&gt;bossMadeMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;fromUTF8&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="n"&gt;modified&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, I've glossed over the profunctor-ness (profunctor-iality? profunctor-tude?) of &lt;code&gt;((+) 1.0)&lt;/code&gt;, but it's time to address that. Let's see how &lt;code&gt;dimap&lt;/code&gt; is implemented for functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;profunctorFunction&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At &lt;a href="https://meeshkan.com" rel="noopener noreferrer"&gt;Meeshkan&lt;/a&gt;, we work a lot with IO (we're in the business of testing servers), so having "the server typeclass" (aka &lt;code&gt;Profunctor&lt;/code&gt;) is invaluable as we build up mock servers from primitives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our first profunctor optic - Iso
&lt;/h2&gt;

&lt;p&gt;If you look at the signature of &lt;code&gt;dimap&lt;/code&gt;, you can read it a few different ways. One way is that it returns a profunctor &lt;code&gt;p s t&lt;/code&gt;. But another way, and one that is closer to that of &lt;code&gt;map&lt;/code&gt;, is that it returns a function between profunctors &lt;code&gt;p a b -&amp;gt; p s t&lt;/code&gt;. When &lt;code&gt;s == t&lt;/code&gt; and &lt;code&gt;a == b&lt;/code&gt;, another way to look at &lt;code&gt;dimap (s -&amp;gt; a) (a -&amp;gt; s)&lt;/code&gt; is that it has the potential to create an isomorphism between &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt;, ie converting a map to a list of tuples and back again. In this case, and if there is no funny business (ie deleting entries), the two can be used interchangeably.&lt;/p&gt;

&lt;p&gt;In lens-land, &lt;code&gt;dimap&lt;/code&gt; is called &lt;code&gt;iso&lt;/code&gt; for this reason.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll also rebrand the signature &lt;code&gt;p a b -&amp;gt; p s t&lt;/code&gt; as an &lt;strong&gt;Iso&lt;/strong&gt; so that it's easier to understand the contract. Meaning that if you give me &lt;code&gt;(s -&amp;gt; a) -&amp;gt; (b -&amp;gt; t)&lt;/code&gt;, I'll give you back a &lt;code&gt;p a b -&amp;gt; p s t&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Iso&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&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;forall&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Iso&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In general, a &lt;em&gt;profunctor optic&lt;/em&gt; is a function with the signature &lt;code&gt;p a b -&amp;gt; p s t&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You may be wondering, "Why are there two names for that thing profunctors do - &lt;code&gt;dimap&lt;/code&gt; and &lt;code&gt;iso&lt;/code&gt;?" The reason is because the profunctor of implementation of optics came about &lt;em&gt;after&lt;/em&gt; optics were invented. The genius of the profunctor implementation is that one of the classic optics - Iso - is the &lt;code&gt;dimap&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- "4.1416"&lt;/span&gt;
&lt;span class="n"&gt;iso&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- "4.1416"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A stronger profunctor
&lt;/h2&gt;

&lt;p&gt;Now, imagine that "The Plus One Server" is getting used more and, as is natural with servers, we want to hook it up to other services. While other "more sophisticated" services have some sort of logging, our mighty &lt;code&gt;((+) 1.0)&lt;/code&gt; lacks logging capabilities. So how can "The Plus One Server" take logs from upstream services and pass them to downstream services?&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- craaasssshhh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wouldn't it be nice if we could just ignore the log? We'd need to beef up our profunctor with a bit more muscle so it can "carry" the log in addition to the payload. In short, we need to make our server &lt;em&gt;stronger&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Strong&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now, let's make The Plus One Server strong.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;myLog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="s"&gt;"someLog"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- Tuple "4.1416" "someLog"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;first&lt;/code&gt; upgrades &lt;code&gt;((+) 1.0)&lt;/code&gt; to carry the log from the input to the output.&lt;/p&gt;

&lt;p&gt;So what does this have to do with profunctor optics? What if we want to carry a map back to the incoming object?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;mapBackHome&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mapBackHome&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, &lt;code&gt;show&lt;/code&gt; is our "map back" from &lt;code&gt;readFloat&lt;/code&gt;. It tells us how to convert the input to the output. We call a function between strong profunctors a &lt;strong&gt;Lens&lt;/strong&gt; when it carries a map back home.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Strong&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="n"&gt;inputWithMap&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt;
    &lt;span class="n"&gt;inputWithMap&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;backHome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;backHome&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the type of &lt;strong&gt;Lens&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Lens&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&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;forall&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Strong&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we could have written the above definition as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Strong&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Lens&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="n"&gt;inputWithMap&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt;
    &lt;span class="n"&gt;inputWithmap&lt;/span&gt;
    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;backHome&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;backHome&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because optics are functions, we can compose them. Let's see how that works with lenses and our server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;mapBackToString&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mapBackToString&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;

&lt;span class="n"&gt;mapBackToUTF8&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;ByteString&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;ByteString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;mapBackToUTF8&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fromUTF8&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;toUTF8&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="n"&gt;mapBackToUTF8&lt;/span&gt; &lt;span class="c1"&gt;-- lens 1&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="n"&gt;mapBackToString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- lens 2&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- server&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withOctets&lt;/span&gt; &lt;span class="n"&gt;pack&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0xAB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xCD&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;-- "4.1416"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though lenses allow a different output type, for the purposes of this tutorial, we're using &lt;code&gt;Lens s s a a&lt;/code&gt;, which is defined as &lt;code&gt;Lens'&lt;/code&gt; in &lt;a href="https://github.com/purescript-contrib/purescript-profunctor-lenses" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-profunctor-lenses&lt;/code&gt;&lt;/a&gt;. In general, when you "zoom out" from a lens, you want to get back to where you started, so &lt;code&gt;Lens'&lt;/code&gt; is enough for most cases.&lt;/p&gt;

&lt;p&gt;Although we're using our hand-rolled lens function above, it is exactly the same one as in &lt;a href="https://github.com/purescript-contrib/purescript-profunctor-lenses" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-profunctor-lenses&lt;/code&gt;&lt;/a&gt; with a slightly different name. They call it &lt;code&gt;lens'&lt;/code&gt;, and they use &lt;code&gt;lens&lt;/code&gt; as a helper function to build &lt;code&gt;lens'&lt;/code&gt;. Try subbing &lt;code&gt;lens&lt;/code&gt; above out for &lt;code&gt;Data.Lens.lens'&lt;/code&gt; and see for yourself!&lt;/p&gt;

&lt;h2&gt;
  
  
  Give us a choice!
&lt;/h2&gt;

&lt;p&gt;So "The Plus One Server" is the talk of the town, and other devs are starting to notice. Some are a little bit angry because they've never asked for a &lt;code&gt;((+) 1.0)&lt;/code&gt; and now it is part of their stack. A colleague approaches us and says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Congrats on your accomplishment with "The Plus One Server." But now it's everywhere downstream and I don't work with numbers. Can you just ignore my input when you see it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aiming to please, we see what we can do!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- how I'll use The Plus One Server&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- craaasssshhh&lt;/span&gt;
&lt;span class="c1"&gt;-- how my colleague's data will pass through the server&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- craaasssshhh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How do we deal with this? We have a &lt;em&gt;choice&lt;/em&gt; between two data types, and our server needs to be a profunctor that can adapt accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Choice&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&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;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Armed with &lt;code&gt;Choice&lt;/code&gt;, we can build a server that can act on our data and pass through our colleague's data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- how i'll use The Plus One Server&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- == "4.1416"&lt;/span&gt;
&lt;span class="c1"&gt;-- how my colleague will use my server&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- == "Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another choice we can make is whether to attempt the computation at all. If our server can process the information, great, and if not, we provide a sensible default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;sensibleDefault&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;
&lt;span class="n"&gt;sensibleDefault&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;if&lt;/span&gt; &lt;span class="n"&gt;isNaN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;then&lt;/span&gt; &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="kr"&gt;else&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In lens-land, this is called a &lt;strong&gt;Prism&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;prism&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Choice&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Either&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="n"&gt;prism&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;fro&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt; &lt;span class="n"&gt;fro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can use it for our server like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;prism&lt;/span&gt; &lt;span class="n"&gt;sensibleDefault&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- == "4.1416"&lt;/span&gt;
&lt;span class="n"&gt;prism&lt;/span&gt; &lt;span class="n"&gt;sensibleDefault&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"not a number"&lt;/span&gt; &lt;span class="c1"&gt;-- == "not a number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So prisms give us a &lt;em&gt;choice&lt;/em&gt; thanks to the &lt;strong&gt;Choice&lt;/strong&gt; profunctor&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about security?
&lt;/h2&gt;

&lt;p&gt;"The Plus One Server" is &lt;em&gt;so&lt;/em&gt; hot that hackers have noticed it and are trying to reverse engineer it to understand its inner workings and exploit its vulnerabilities. The boss, dismayed, starts saying stuff like "we need to lock this thing down" and "does anyone here know about end-to-end encryption?"&lt;/p&gt;

&lt;p&gt;Your colleagues scramble to implement a crude form of encryption:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;locked&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;locked&lt;/span&gt; &lt;span class="s"&gt;"passw0rd"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- craaasssshhh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So some upstream service "locks" our operation with a password, and they later unlock it with their super-secure password &lt;code&gt;"passw0rd"&lt;/code&gt;. Of course, we have no clue what to do with a function that takes a password and produces a number. Our humble server can only work with numbers! Unless we are armed with a &lt;strong&gt;Closed&lt;/strong&gt; profunctor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Closed&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&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;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A way to think about lock is that it delays application of our function until the point when a password is provided. Another way to imagine it is that it sends the function to the end-user and lets them apply it with their password. I would guess that this is the &lt;em&gt;exact&lt;/em&gt; algorithm WhatsApp uses for their end-to-end encryption.&lt;/p&gt;

&lt;p&gt;Back to "The Plus One Server", it can now handle password-protected data:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;locked&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;locked&lt;/span&gt; &lt;span class="s"&gt;"passw0rd"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- == "4.1416"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In functional-programming land, passwords can be anything. Strings, ints, aaannnd..... functions! Yes, passwords can be functions - but why would one do this?&lt;/p&gt;

&lt;p&gt;A password "unlocks" our lock, so a function unlocking something would mean that it provides information for a computation to continue. For example, think about image processing. We have a killer algorithm to do something like Gaussian blur or masking, but we don't want to know &lt;em&gt;how&lt;/em&gt; the user applies it to their picture. Their &lt;em&gt;use&lt;/em&gt; of our algorithm is private, and this use is encoded in a function. We'll call this form of password-protection with a function a &lt;strong&gt;Grate&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Here, (s -&amp;gt; a) will be our "function" password&lt;/span&gt;
&lt;span class="n"&gt;grate&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;span class="n"&gt;grate&lt;/span&gt; &lt;span class="n"&gt;unlock&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;unlock&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The types going to &lt;code&gt;dimap&lt;/code&gt; are a bit hard to follow, so let's write &lt;code&gt;dimap&lt;/code&gt; just using its types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;dimap&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- input&lt;/span&gt;
  &lt;span class="p"&gt;(((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- output&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;-- internal profunctor&lt;/span&gt;
  &lt;span class="c1"&gt;-- yields p s t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that, all the way through, &lt;code&gt;(s -&amp;gt; a)&lt;/code&gt; is our password for the closed profunctor. Or, subbing &lt;code&gt;(s -&amp;gt; a)&lt;/code&gt; into the definition of &lt;code&gt;Closed&lt;/code&gt;, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Closed&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
&lt;span class="c1"&gt;-- remembering that&lt;/span&gt;
&lt;span class="c1"&gt;-- lock :: forall a b x. p a b -&amp;gt; p (x -&amp;gt; a) (x -&amp;gt; b)&lt;/span&gt;
&lt;span class="c1"&gt;-- when using a function (s -&amp;gt; a), polymorphism turns this into&lt;/span&gt;
   &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your brain is hurting, rest assured that that's as heady as it gets. Now we can actually use our grate to do some password-protected art with the &lt;code&gt;((+) 1.0)&lt;/code&gt; server.&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;RGB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;

&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;
&lt;span class="n"&gt;red&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;

&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;
&lt;span class="n"&gt;green&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;

&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;
&lt;span class="n"&gt;blue&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

&lt;span class="n"&gt;myFilter&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt;
&lt;span class="n"&gt;myFilter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;green&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;grate&lt;/span&gt; &lt;span class="n"&gt;mySecretFilterApplication&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;RGB&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- == (RGB 4.0 2.0 3.0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;((+) 1.0)&lt;/code&gt; server did its magic without ever knowing the inner workings of your algorithm. The "passwords" here were &lt;code&gt;green&lt;/code&gt;, &lt;code&gt;blue&lt;/code&gt; and &lt;code&gt;red&lt;/code&gt;. When mixed with our &lt;code&gt;((+) 1.0)&lt;/code&gt;, they produced a new pixel.&lt;/p&gt;

&lt;p&gt;In general, when thinking about password protecting something or, more generally, hiding the application of an algorithm like the one above, closed profunctors and grates are your friend!&lt;/p&gt;

&lt;h2&gt;
  
  
  Make me a Star
&lt;/h2&gt;

&lt;p&gt;We've now deemed "The Plus One Server" to be so useful that we want to use it with exotic optics that we've never even heard of. So far, we have only been dealing with optics that accept one profunctor - the function. But there are lots of nice profunctors, and we'd like to work with them somehow.&lt;/p&gt;

&lt;p&gt;One such profunctor is the &lt;strong&gt;Kleisli&lt;/strong&gt; profunctor. It is a profunctor with a side effect mixed in. So if you take the &lt;code&gt;Function&lt;/code&gt; profunctor we've seen before &lt;code&gt;a -&amp;gt; b&lt;/code&gt;, a Kleisli profunctor is that with a little something extra like write to a log, read from an environment or launch a rocket. The signature for a Kleisli profunctor, also called a &lt;strong&gt;Star&lt;/strong&gt;, is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;functorStar&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;profunctorStar&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="n"&gt;ft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Star&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ft&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;f&lt;/code&gt; represents the side effect and &lt;code&gt;b&lt;/code&gt; represents the output value. This could be something like &lt;code&gt;Log Int&lt;/code&gt; or &lt;code&gt;Array String&lt;/code&gt; or &lt;code&gt;RocketLauncher Number&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I don't know why they call it &lt;strong&gt;Star&lt;/strong&gt;, but it seems like a reasonable choice. I tried singing "Twinkle Twinkle Little Kleisli" to my kid and it didn't really work, so let's stick with Star.&lt;/p&gt;

&lt;p&gt;Anyway, the boss wants to use an optic from Kleisli-Land, and we're responsible for getting it to integrate with our system. Our profunctor that makes a foray into Kleisli-land is called &lt;strong&gt;Wander&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Wander&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;StarOptic&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Optic&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first argument is an optic of star profunctors. The return value is also an optic, but one that can be used by &lt;em&gt;any&lt;/em&gt; profunctor that implements Wander. Under the hood, our profunctor call the Kleisli (Star) optic. That means that it'll have to know how to add &lt;em&gt;and&lt;/em&gt; remove a side effect - adding when it enters Kleisli-land and removing when it leaves.&lt;/p&gt;

&lt;p&gt;The actual signature for Wander in purescript is a bit different. I'm not sure why they made it this way, but it is isomorphic to the one above and gets the job done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- real signature&lt;/span&gt;
&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kt"&gt;Wander&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make this more concrete, let's look at the implementation of Wander for the &lt;code&gt;Function&lt;/code&gt; profunctor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;wanderFunction&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Wander&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="n"&gt;kleisli&lt;/span&gt; &lt;span class="n"&gt;ourfunc&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unwrap&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;kleisli&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Identity&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ourfunc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;-- you can also use this, which is more concise&lt;/span&gt;
  &lt;span class="c1"&gt;-- wander t = alaF Identity t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, let's imagine that we got a Kleisli function that lifted a side effect from one operation to another. This is common when, for example, an operation fails for a part of a whole and you need to mark the whole as "failed".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Client&lt;/span&gt; &lt;span class="o"&gt;=&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;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;actOnBalance&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Applicative&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Number&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kt"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kt"&gt;Person&lt;/span&gt;
&lt;span class="n"&gt;actOnBalance&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&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="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we try using with "The Plus One Server", it will predictably crash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;actOnBalance&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&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="s"&gt;"Mike"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;-- crasssshhhh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if we make ((+) 1.0) effectful, it is able to wander into Kleisli-land by using &lt;code&gt;Identity&lt;/code&gt; under the hood, as we saw above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="n"&gt;actOnBalance&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&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="s"&gt;"Mike"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;-- == { name: "Mike", balance: 0.0 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luckily, there is a whole category of functions that behave like &lt;code&gt;actOnBalance&lt;/code&gt;. They're called &lt;code&gt;traverse&lt;/code&gt;, and they work on types that implement the &lt;code&gt;Traversable&lt;/code&gt; typeclass.&lt;/p&gt;

&lt;p&gt;The basic contract with something implementing &lt;code&gt;Traversable&lt;/code&gt; is that, if you have a container of values and you can produce a side effect for each value in the container, then you can accumulate the side effects. For example, if you have a &lt;code&gt;List&lt;/code&gt; of &lt;code&gt;Writer Int&lt;/code&gt; (meaning integers we're keeping some sort of log about), then we can get a &lt;code&gt;Writer (List Int)&lt;/code&gt; by accumulating the logs for each &lt;code&gt;Int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's look at the signature for traverse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;traverse&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;Traversable&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Applicative&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&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;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is exactly the same as the first argument to &lt;code&gt;wander&lt;/code&gt;, with &lt;code&gt;s == t a&lt;/code&gt; and &lt;code&gt;t == t b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This means that we can create a utility for anything implementing &lt;code&gt;Traversable&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;traversal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="n"&gt;traverse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's use it with our friend &lt;code&gt;((+) 1.0)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;traversal&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- [2.0, 3.0, 4.0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remembering that we can compose optics, let's use it with the lens from above:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;traversal&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;s&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="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"3.0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- ["2.0", "3.0", "4.0"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In summary, a profunctor implementing &lt;code&gt;Wander&lt;/code&gt; allows us to take a stroll in Kleisli-Land, and it can be used in lots of different contexts. We saw two of them above - &lt;code&gt;actOnBalance&lt;/code&gt; and the mega-useful &lt;code&gt;traversal&lt;/code&gt;. Wander will be even more useful when we talk about folds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Folding up values
&lt;/h2&gt;

&lt;p&gt;So far, our workhorse profunctor has been the function, and even when we wandered into Kleisli-land, we did so to import our results back to the world of functions. Remembering that optics are functions between profunctors, when we give a &lt;code&gt;Function&lt;/code&gt; to an optic as an argument, we call that a &lt;strong&gt;Setter&lt;/strong&gt;. This is how "The Plus One Server" worked - it is a function (profunctor) that we passed to an optic (function acting on profunctors) and it set something on the inside of a larger structure (ie an array of integers in a traversal or a RGB channel in a grate).&lt;/p&gt;

&lt;p&gt;While this metaphor is helpful, it is admittedly like a bad monad tutorial (sorry), in that it specializes the idea of profunctors too narrowly. Profunctors are a generalized way to reason about I/O, and there's more to I/O than just functions.&lt;/p&gt;

&lt;p&gt;One thing that comes up a lot with I/O is intentionally suppressing the output. For example, you can ignore the output value and instead return something else. In Purescript, this is called &lt;code&gt;Forget&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;newtype&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;forgetfulProfunctor&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Profunctor&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;forgetfulStrong&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Strong&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;fst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;snd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- 42&lt;/span&gt;
&lt;span class="n"&gt;dimap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- Forget true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We catch the input (&lt;code&gt;true&lt;/code&gt;) and forget about the output.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Fold&lt;/strong&gt; is a profunctor optic that is evaluated with a &lt;code&gt;Forget&lt;/code&gt; profunctor. A &lt;strong&gt;Getter&lt;/strong&gt; is a special fold that uses the &lt;code&gt;identity&lt;/code&gt; function as its accumulator. Let's build up &lt;code&gt;view&lt;/code&gt; defined in &lt;a href="https://github.com/purescript-contrib/purescript-profunctor-lenses" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-profunctor-lenses&lt;/code&gt;&lt;/a&gt; step by step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;lens&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;dimap&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="n"&gt;b&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;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;
&lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- Forget 3.1416&lt;/span&gt;
&lt;span class="n"&gt;forgetForget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&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;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
&lt;span class="n"&gt;forgetForget&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- 3.1416&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;profunctor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;forgetForget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profunctor&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;lens&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Tuple&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readFloat&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"3.1416"&lt;/span&gt; &lt;span class="c1"&gt;-- 3.1416&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our view function below is isomorphic to the one you'll find in &lt;a href="https://github.com/purescript-contrib/purescript-profunctor-lenses" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-profunctor-lenses&lt;/code&gt;&lt;/a&gt;. It's quite concise!&lt;/p&gt;

&lt;p&gt;The issue with &lt;code&gt;Forget&lt;/code&gt; is that it can't forget something that doesn't exist. For example, let's try to make &lt;code&gt;Forget&lt;/code&gt; an instance of &lt;code&gt;Choice&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;forgetChoice&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Choice&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&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;=&lt;/span&gt; &lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt; &lt;span class="c1"&gt;-- craaashhhh&lt;/span&gt;
  &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&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;=&lt;/span&gt; &lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="o"&gt;???&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;-- craaashhhh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem is that we can't pass through a &lt;code&gt;b&lt;/code&gt; because we're forgetting it - we just have &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;r&lt;/code&gt;. So how can we get around this? When we don't have an &lt;code&gt;a&lt;/code&gt; for &lt;code&gt;(a -&amp;gt; r)&lt;/code&gt;, we need to be able to pull an &lt;code&gt;r&lt;/code&gt; out of thin air. What is the typeclass of things where you can pull one out of thin air? The monoid! The function to do that is &lt;code&gt;mempty&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;mempty&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="c1"&gt;-- == ""&lt;/span&gt;
&lt;span class="n"&gt;mempty&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="c1"&gt;-- Nil&lt;/span&gt;
&lt;span class="n"&gt;mempty&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="c1"&gt;-- []&lt;/span&gt;
&lt;span class="n"&gt;mempty&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="c1"&gt;-- Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So as long as &lt;code&gt;r&lt;/code&gt; above is a monoid, we can have our &lt;code&gt;Choice&lt;/code&gt; profunctor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;forgetChoice&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Monoid&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Choice&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&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;=&lt;/span&gt; &lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&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;=&lt;/span&gt; &lt;span class="n"&gt;either&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same trick works for &lt;code&gt;Wander&lt;/code&gt; but on a functor application level. Again, &lt;code&gt;r&lt;/code&gt; will be a monoid, and the &lt;code&gt;Const&lt;/code&gt; functor will "pull an &lt;code&gt;r&lt;/code&gt; out of thin air" if not provided one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;wanderForget&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Monoid&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Wander&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;wander&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Forget&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alaF&lt;/span&gt; &lt;span class="kt"&gt;Const&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="n"&gt;applicativeConst&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Monoid&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Applicative&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Const&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Const&lt;/span&gt; &lt;span class="n"&gt;mempty&lt;/span&gt; &lt;span class="c1"&gt;-- "out of thin air"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, when you try to preview a value from an empty list using a lens library as we do below, you get &lt;code&gt;Nothing&lt;/code&gt; because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;Wander&lt;/code&gt; instance of forget uses the &lt;code&gt;Const&lt;/code&gt; profunctor&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;Const&lt;/code&gt; profunctor, when used in List's implementation of &lt;code&gt;traverse&lt;/code&gt;, starts with a pure const (getting an &lt;code&gt;mempty&lt;/code&gt;, or a &lt;code&gt;Nothing&lt;/code&gt; in this case)&lt;/li&gt;
&lt;li&gt;as there is nothing to smoosh, it returns &lt;code&gt;Nothing&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="n"&gt;preview&lt;/span&gt; &lt;span class="n"&gt;traversed&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Nil&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Going back to Kleisli-land, the &lt;code&gt;Const&lt;/code&gt; functor is the side effect that allows us to &lt;code&gt;Wander&lt;/code&gt; into a &lt;code&gt;Star&lt;/code&gt; profunctor (in this case, the function traversal), get its benefits, and bring them back home to our optic.&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr
&lt;/h2&gt;

&lt;p&gt;When building a server (when using a profunctor), here are some cool optics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;iso&lt;/strong&gt; is a profunctor whose input &lt;em&gt;and&lt;/em&gt; output are isometric to some other value.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;lens&lt;/strong&gt; is strong 💪 enough to drill down into a value and carry a map so we know how to get back up.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;prism&lt;/strong&gt; gives us a choice 🤷‍♂️ between a value and a sensible default if we can't process the value.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;traversal&lt;/strong&gt; allows us to wander 🏃‍♀️ into Kleisli-land and back to do our bidding&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;grate&lt;/strong&gt; allows us to lock 🔒 our optic and unlock it with a key, where the key is a function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And as optics are just functions from profunctor to profunctor, here are two profunctors you can use with optics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Function&lt;/strong&gt; profunctor (&lt;code&gt;a -&amp;gt; b&lt;/code&gt;), which is called &lt;code&gt;Setter&lt;/code&gt;, and whose magic we've seen in "The Plus One Server."&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Forget&lt;/strong&gt; profunctor, that accepts &lt;code&gt;a&lt;/code&gt;'s and "forgets them" in a recepticle called &lt;code&gt;r&lt;/code&gt;, ignoring the output &lt;code&gt;b&lt;/code&gt;. A forget that maps &lt;code&gt;a&lt;/code&gt; to itself is called a &lt;code&gt;Getter&lt;/code&gt;, aka &lt;code&gt;Forget identity&lt;/code&gt;. The general operation is called a &lt;code&gt;Fold&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember, these are just &lt;em&gt;representations&lt;/em&gt; of the concept of optics. There are many ways to build up optics, and the profunctor one is one way. It is my favorite way because it gives you an expressive vocabulary to solve problems. At &lt;a href="https://meeshkan.com" rel="noopener noreferrer"&gt;Meeshkan&lt;/a&gt;, we use custom optics and profunctors all over the place for different business cases, and the nice thing about the PureScript community is that we can share these solutions and get their feedback.&lt;/p&gt;

&lt;p&gt;In this post, I've tried to build up intuition about what profunctors are and show how lenses are derived from them. Usually, when I use a library like &lt;a href="https://github.com/purescript-contrib/purescript-profunctor-lenses" rel="noopener noreferrer"&gt;&lt;code&gt;purescript-profunctor-lenses&lt;/code&gt;&lt;/a&gt;, I'm happy just to use the library without understanding what's going on under the hood. However, the concepts used to implement profunctor lenses are so useful/universal that they're worth exploring in their own right. I hope they help you too as you solve new and exciting challenges!&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>profunctors</category>
      <category>optics</category>
      <category>functional</category>
    </item>
    <item>
      <title>Launching first-class support for automated GraphQL testing</title>
      <dc:creator>Makenna Smutz</dc:creator>
      <pubDate>Wed, 26 Aug 2020 13:28:17 +0000</pubDate>
      <link>https://dev.to/meeshkan/launching-first-class-support-for-automated-graphql-testing-3p3p</link>
      <guid>https://dev.to/meeshkan/launching-first-class-support-for-automated-graphql-testing-3p3p</guid>
      <description>&lt;p&gt;GraphQL is the future of APIs that we at Meeshkan, are investing in. &lt;strong&gt;Today we are announcing our full focus on automated testing of GraphQL servers.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rdxRFMPh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.graphcms.com/locUhpIeToGAvxskJoda" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rdxRFMPh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.graphcms.com/locUhpIeToGAvxskJoda" alt="An example query with the corresponding, generated test report."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this is your first time hearing about &lt;a href="https://meeshkan.com/"&gt;Meeshkan&lt;/a&gt; — we're an automated testing service for the backend of your app using NLP and property-based testing. This announcement is us focusing deeper on developing future features unique to GraphQL testing. We wholeheartedly believe in the benefits the technology brings, as well as the need for better testing of GraphQL APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does this sound interesting to you? -&amp;gt;&lt;/strong&gt; &lt;a href="https://app.meeshkan.com"&gt;Create a free Meeshkan account&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, we'll walk through what led us to bet our whole company's future on this technology - and how that affects you and your testing workflow!&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The evolution of API technology&lt;/li&gt;
&lt;li&gt;Why we believe GraphQL will become the standard choice for building new APIs&lt;/li&gt;
&lt;li&gt;What does first-class GraphQL server testing look like?&lt;/li&gt;
&lt;li&gt;How automated GraphQL tests work on your server&lt;/li&gt;
&lt;li&gt;Benefits of using Meeshkan with your GraphQL API vs your REST API&lt;/li&gt;
&lt;li&gt;The future of testing GraphQL as Meeshkan sees it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The evolution of API technology
&lt;/h2&gt;

&lt;p&gt;Modern web APIs entered into the development world in 1999 in numerous implementations. One of the first business APIs, Salesforce debuted it's &lt;a href="https://apievangelist.com/2012/12/20/history-of-apis/"&gt;XML is also known as SOAP API&lt;/a&gt; in 2000.&lt;/p&gt;

&lt;h3&gt;
  
  
  RESTful
&lt;/h3&gt;

&lt;p&gt;In the same year, &lt;a href="https://blog.readme.com/the-history-of-rest-apis/"&gt;Roy Fielding&lt;/a&gt; and a few colleagues created a standard for APIs now regarded as REST. The doctoral dissertation detailing REST's standards was created with the input of the development community. It contained several features that are critical/common practice today, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using HTTP verbs (GET, PUT, POST, DELETE)&lt;/li&gt;
&lt;li&gt;Stateless-ness (not containing context other than the specific request being made)&lt;/li&gt;
&lt;li&gt;Cache-ability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The motivation was to give APIs a common set of standards to rally around and improve as a singular community. The vast majority of production APIs today were originally built following the REST specification (and most are still).&lt;/p&gt;

&lt;p&gt;There are several challenges that the REST APIs afford. One of those challenges relates to testing — the lack of generated documentation. &lt;/p&gt;

&lt;p&gt;Documentation is important for developers (internal or external) using the API. Many teams with REST APIs use &lt;a href="https://swagger.io/specification/"&gt;OpenAPI&lt;/a&gt; or &lt;a href="https://swagger.io/"&gt;Swagger&lt;/a&gt; as a set of rules that describes the format of their REST API. This is great for understanding what the API is capable of without reading the code. It also provides the structure to create mock APIs to test against. OpenAPI specifications have &lt;a href="https://stoplight.io/"&gt;great tooling&lt;/a&gt; but are brittle to API changes if manually created — which is common practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL
&lt;/h3&gt;

&lt;p&gt;The initial prototype of GraphQL came to life in 2012 as a side project by a few Facebook developers. These developers were facing challenges with their existing Newsfeed REST API. The static &lt;a href="https://spec.graphql.org/"&gt;specification&lt;/a&gt; draft was released in 2015 and warmly embraced by the development community. The API specification was designed for the developer who'd be using the API at the core focus and dealing with the technology to make it work after. &lt;/p&gt;

&lt;p&gt;Following the design, the features that the GraphQL specification landed include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical nesting&lt;/strong&gt;: Deeply defining the association of the data stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strongly typed&lt;/strong&gt;: GraphQL types allow the client to predict what the query will return without knowing that much about the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Introspection&lt;/strong&gt;: Access to the entire type system/specification of a schema based on its endpoint. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remember GraphQL introspection. It will become important when speaking about automated testing of GraphQL APIs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Introspection&lt;/strong&gt; | noun | the examination or observation of one's own processes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using an introspection query, we can conclude the GraphQL schema contents and types. With this ruleset of how the API should act and some Natural Language Processing magic — we're able to generate meaningful tests.&lt;/p&gt;

&lt;p&gt;For some more history of GraphQL, Honeypot.io has created an insightful documentary:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why we believe GraphQL will become the standard choice for building new APIs
&lt;/h2&gt;

&lt;p&gt;Processes as precedented as creating an API are resistant to change. Thankfully at the core, the two technologies are very similar. Both REST and GraphQL send an HTTP request and receive a response. GraphQL has many elements of the REST standard built into its functionality with upgrades to its developer experience.&lt;/p&gt;

&lt;p&gt;As a company that has been focused on &lt;a href="https://meeshkan.com/blog/what-is-the-testing-pyramid/"&gt;testing&lt;/a&gt;, &lt;a href="https://meeshkan.com/blog/on-device-mocking-of-rest-apis-in-react-native/"&gt;mocking&lt;/a&gt;, and &lt;a href="https://meeshkan.com/blog/why-not-use-real-apis-in-tests/"&gt;use&lt;/a&gt; of APIs for the past few years, GraphQL has been on our radar for a while. And several of our team members were early adopters of GraphQL.&lt;/p&gt;

&lt;p&gt;We as a team are now bought into the GraphQL ecosystem in our own stack using &lt;a href="https://www.8base.com/"&gt;8base&lt;/a&gt; as our database. It's a MySQL database with a GraphQL API and a beautiful UI - but the preconfigured endpoint that we could query against was the decision settler.&lt;/p&gt;

&lt;p&gt;Another sign that GraphQL will continue to be in the stack-of-choice is the &lt;a href="https://graphql.org/users/"&gt;growing number of software industry leaders&lt;/a&gt; making exactly that choice. GitHub, one of the largest and most used developer tools, has a great GraphQL API and built-in documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does first-class GraphQL server testing look like?
&lt;/h2&gt;

&lt;p&gt;The first thing to clarify is that several parts of a GraphQL API that can be tested. The GraphQL query (including queries, mutations, and subscriptions), the GraphQL resolver, and the GraphQL server.&lt;/p&gt;

&lt;p&gt;Depending on how you build your GraphQL schema, there are different parts of testing that could serve your team:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you use a service such as &lt;a href="https://graphcms.com/"&gt;GraphCMS&lt;/a&gt; or &lt;a href="https://www.8base.com/"&gt;8base&lt;/a&gt; - they take care of building and managing the resolvers and server for you. If this is your case, it'd be most helpful to encourage your provider to use Meeshkan as your tests would need to be frontend focused.&lt;/li&gt;
&lt;li&gt;If you've built your GraphQL API from scratch using something like &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt; or &lt;a href="https://www.apollographql.com/"&gt;Apollo&lt;/a&gt;, you're in charge of maintaining all three parts of the API. Meeshkan is currently a tool for the resolvers and the server-side of your API. We make sure your auth is impenetrable and there aren't loopholes such as data accepted that will crash the server and more.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At Meeshkan, committing to first-class support means making decisions about data science algorithms, communities to invest in, and testing capabilities — &lt;strong&gt;with GraphQL at the focus&lt;/strong&gt;. Possibly at the detriment to existing REST focused algorithms, other communities that might be interested in using Meeshkan, and the ability to test other API types. Of course, we keep a close eye on the divergence, but rest &lt;em&gt;cough 🤷‍♀️&lt;/em&gt; assured if you're building with a GraphQL API, we're dedicated.&lt;/p&gt;

&lt;p&gt;Some things we are exploring on our roadmap&lt;/p&gt;

&lt;h2&gt;
  
  
  How automated GraphQL tests work on your server
&lt;/h2&gt;

&lt;p&gt;Using your GraphQL endpoint, Meeshkan dynamically generates and executes a series of property-based tests. There are a lot of moving pieces here that I want to break down the mechanics of.&lt;/p&gt;

&lt;p&gt;First, when importing a project into Meeshkan, you're asked for either the location of your Open API specification and/or your project's GraphQL endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KxN3V-9k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.graphcms.com/vIthC9RqTUycJUhffO7c" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KxN3V-9k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://media.graphcms.com/vIthC9RqTUycJUhffO7c" alt="Screenshot of the build settings from the Meeshkan webapp. At the bottom, there is an input for your GraphQL endpoint."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're in the middle of a migration from REST to GraphQL or need to authenticate in REST but work with GraphQL, we support testing with both APIs in tandem! &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The biggest challenges of automated software testing are dynamically generating tests as the code changes and making sure those tests are meaningful and high quality.&lt;/p&gt;

&lt;p&gt;Our approach to this challenge is to base off of a concrete set of rules (in this case the GraphQL schema) and build from there. We use Natural Language Processing to generate reasonable inputs for fields with names like &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;. Starting from a certain (yet dynamic) base assures we know the results are actual, production reproducible scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of using Meeshkan with your GraphQL API vs your REST API
&lt;/h2&gt;

&lt;p&gt;Alongside the benefits of &lt;em&gt;using&lt;/em&gt; a GraphQL API, there are several benefits of the inherent structure and functionality that make it more compatible for testing.&lt;/p&gt;

&lt;p&gt;GraphQL APIs are strongly typed. And while we are big fans of &lt;a href="https://meeshkan.com/blog/functional-programming-for-frontend-pipe/"&gt;strongly typed patterns in programming&lt;/a&gt; at Meeshkan, I digress. The native feature of a GraphQL schema, called introspection, allows the entire type structure and relationships to be queried on-demand, and dynamically as the API evolves.&lt;/p&gt;

&lt;p&gt;Another feature that provides testing value, is the documentation of relationships. One feature we're passionate about at Meeshkan is stateful testing. We believe that for your tests to be meaningful, they should replicate a user in the wild — also known as your production app.&lt;/p&gt;

&lt;p&gt;Most tools that &lt;em&gt;automatically&lt;/em&gt; test your app, read the code statically, and make inferences. Meeshkan imitates a user with our integration tests. Stateful tests create users with traceable/reproducible steps that center around logic-heavy functions in your app. Some examples where stateful testing is invaluable include authorization, authentication, and transactions (currency, databases, etc).&lt;/p&gt;

&lt;p&gt;GraphQL stores information about how mutations relate to queries. This gives confidence to our stateful testing algorithms. &lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;tests&lt;/code&gt; can be traced to &lt;code&gt;createTest&lt;/code&gt; and &lt;code&gt;createManyTests&lt;/code&gt;. With a REST API, there are common patterns that our NLP algorithms can pick up — but assumptions make for a lot less confident tests. For more complex relationships, we support custom GraphQL directives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future of testing GraphQL as Meeshkan sees it
&lt;/h2&gt;

&lt;p&gt;I'm super stoked to finally announce what we've been brewing internally and working with early adopters. We've got a vision that testing should be intertwined into your dynamic coding workflow, rather than a disconnected, skippable step. We're working hard to achieve this - starting in integration testing.&lt;/p&gt;

&lt;p&gt;We're energized by the GraphQL community and the future that we can help developers achieve. A future where 'to test or not to test' is no longer a difficult decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next steps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allowing you to connect your client to test queries, mutations, and subscriptions used in production.&lt;/li&gt;
&lt;li&gt;Creating explicit test cases where you define the queries you'd like to run each test&lt;/li&gt;
&lt;li&gt;Monitoring auth (authentication and authorization) rules, notifying when a user scope has changed&lt;/li&gt;
&lt;li&gt;Is there something that you'd like to see in your testing workflow? &lt;a href="https://meeshkan.com/contact/"&gt;We want to hear from you!&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graphql</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Extension types in TypeScript</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Thu, 06 Aug 2020 16:15:15 +0000</pubDate>
      <link>https://dev.to/meeshkan/extension-types-in-typescript-366a</link>
      <guid>https://dev.to/meeshkan/extension-types-in-typescript-366a</guid>
      <description>&lt;p&gt;When creating a TypeScript library, you will invariably run into a scenario where someone wants to extend it. In JavaScript land, they can do this with the following hack:&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;const&lt;/span&gt; &lt;span class="nx"&gt;yourLibrary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-library&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myExtension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-extension&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;yourLibrary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yourObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;myExtension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myExtension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In TypeScript, this type of thing is generally frowned upon because the type system will not (easily) allow monkey patching. The “classic” workaround is using a cast to the &lt;code&gt;any&lt;/code&gt; type, which effectively de-TypeScript-ifies TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;yourObject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-library&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;myExtension&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-extension&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;yourObject&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;myExtension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myExtension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other problem with this pattern is that it &lt;code&gt;myExtension&lt;/code&gt; is not referenceable on &lt;code&gt;yourObject&lt;/code&gt;, which requires a cast on every access as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;yourObject&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;myExtension&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;myFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we have lost the type-safety of &lt;code&gt;myExtension&lt;/code&gt;. So the TypeScript compiler will no longer check that &lt;code&gt;myFunction&lt;/code&gt; actually exists on &lt;code&gt;myExtension&lt;/code&gt;, let alone what the result of &lt;code&gt;myFunction()&lt;/code&gt; is. Too much of this pattern will render your TypeScript project un-typeable, at which point JavaScript would have been a better option.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do?
&lt;/h2&gt;

&lt;p&gt;One solution is just to make a pull request to the original library to have your extension incorporated into its official package. While this may be a good idea in some scenarios, in most cases extensions are too niche, too broken or too big to be merged into a project. On top of that, pull requests often take a long time to go through review and incorporation into a new release.&lt;br&gt;
Another solution, which is what this article advocates, is building libraries with type-safe extensions as first-class citizens. I realize that this won’t solve your problem here-and-now, but if you are a library author, it will give other developers an easy way to extend your work without necessarily touching the core package. If you are a consumer of a library, a pull-request giving it extensional properties is usually a much easier ask than extending the library with &lt;em&gt;your&lt;/em&gt; specific feature.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two types of extensions
&lt;/h2&gt;

&lt;p&gt;The most common types of extensions developers need are &lt;em&gt;intersection extensions&lt;/em&gt; and &lt;em&gt;union extensions&lt;/em&gt;. Intersection extensions say “Hey, your objects are awesome, but they would be even &lt;em&gt;more&lt;/em&gt; awesome if they did thing X.” Union extensions say “Hey, your objects are awesome, but you’re missing a few that I’d need for scenario Y.” Intersections and unions are part of TypeScript’s core language — the intersection &lt;code&gt;&amp;amp;&lt;/code&gt; and union &lt;code&gt;|&lt;/code&gt; operator are a basic way to build composite types. What I’m advocating is leveraging these operators to supercharge your libraries with extensionality.&lt;/p&gt;
&lt;h3&gt;
  
  
  Intersection extensions
&lt;/h3&gt;

&lt;p&gt;Intersection extensions can be achieved with a generic type (let’s call it &lt;code&gt;U&lt;/code&gt;) that is passed down through your objects and intersected with primitive objects via the &lt;code&gt;&amp;amp;&lt;/code&gt; operator.&lt;/p&gt;

&lt;p&gt;Let’s imagine that your library contains the following two types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Intersection extensions add an intersection to all relevant types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, if we want to add an optional &lt;code&gt;id&lt;/code&gt; to all types, it becomes a simple operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Helsinki&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finland&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Marie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;101&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;Even better, we now have a type-safe accessor for &lt;code&gt;id&lt;/code&gt;, so the following function will pass the TypeScript compiler&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Union extensions
&lt;/h3&gt;

&lt;p&gt;Let’s imagine a different scenario — we are creating types for JSON objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONPrimitive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSONPrimitive&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;JSONArray&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;JSONObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;JSONArray&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s say that we would like JavaScript &lt;code&gt;Date&lt;/code&gt; objects to also be admitted as JSON. Union extensions, which I’ll represent with the letter &lt;code&gt;T&lt;/code&gt;, give us a clean way to do this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONPrimitive&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&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="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSONPrimitive&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;JSONArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;JSONArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can put &lt;code&gt;Date&lt;/code&gt; objects all over our JSON and the TypeScript compiler will not complain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonWithDates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSONValue&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;h3&gt;
  
  
  Runtime validation
&lt;/h3&gt;

&lt;p&gt;If you are using a runtime type validator like &lt;a href="https://github.com/gcanti/io-ts" rel="noopener noreferrer"&gt;&lt;code&gt;io-ts&lt;/code&gt;&lt;/a&gt;, the patterns are quite similar. For intersections, we can use the &lt;code&gt;intersection&lt;/code&gt; function from &lt;code&gt;io-ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;io-ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PersonValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TypeOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recursion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Person&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AddressValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;friends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PersonValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;u&lt;/span&gt;
&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AddressValidator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TypeOf&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;U&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;u&lt;/span&gt;    
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same type of pattern can be used for union types — just pass the a validator to &lt;code&gt;t.union&lt;/code&gt; instead of &lt;code&gt;t.intersection&lt;/code&gt; where needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the code!
&lt;/h2&gt;

&lt;p&gt;This is the strategy I used to build &lt;a href="https://github.com/meeshkan/json-schema-strictly-typed" rel="noopener noreferrer"&gt;&lt;code&gt;json-schema-strictly-typed&lt;/code&gt;&lt;/a&gt;, which creates a typed version of JSON Schema that is extensible with both intersection and union extensions. This way, people can add arbitrary extensions to objects in the Schema (intersection) &lt;em&gt;and&lt;/em&gt; arbitrary new Schema primitives (union).&lt;/p&gt;

&lt;p&gt;From this level of generic-ness (genericity?, generickitude?), it is easy to export helper objects for “base” cases. The base case of an intersection extension is simply a type from which all your objects already extend. In the example above, &lt;code&gt;Person&amp;lt;{}&amp;gt;&lt;/code&gt; and &lt;code&gt;Address&amp;lt;{}&amp;gt;&lt;/code&gt; would be this, as intersecting with &lt;code&gt;{}&lt;/code&gt; is a no-op. For union types, a default extension could be extending the library with a type that already exists in the union. So, for example, &lt;code&gt;JSONSchemaValue&amp;lt;string&amp;gt;&lt;/code&gt; is a no-op.&lt;/p&gt;

&lt;p&gt;I’m looking forward to seeing if this pattern catches on and if the community can come up with tools that help maintain and author TypeScript libraries with extensibility in mind!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>functional</category>
    </item>
    <item>
      <title>Kotlin tests and user stories</title>
      <dc:creator>Mike Solomon</dc:creator>
      <pubDate>Thu, 06 Aug 2020 16:12:22 +0000</pubDate>
      <link>https://dev.to/meeshkan/kotlin-tests-and-user-stories-4pa9</link>
      <guid>https://dev.to/meeshkan/kotlin-tests-and-user-stories-4pa9</guid>
      <description>&lt;p&gt;I love stories. I love tests. And I really love tests that read like stories.&lt;/p&gt;

&lt;p&gt;My journey into the poetic world of writing tests like stories starts with a talk by Jake Wharton about &lt;a href="https://jakewharton.com/testing-robots/" rel="noopener noreferrer"&gt;robot testing&lt;/a&gt;. Wharton argues that tests should read like instructions to a robot on how to use your app. The benefits of his approach go beyond the human-readability of a testing spec. Writing hybrid story/tests enforces a form of rigor that forces one to take a step back and think about how one truly wants users to interact with an app. This invariably leads to a cleaner design and less cruft.&lt;/p&gt;

&lt;p&gt;This way of authoring tests has recently become a bit of an obsession. So much so that I have dispensed with functional syntax and begun writing my tests using prose. Think OuLiPo plus Larry Wall.&lt;/p&gt;

&lt;p&gt;“How does the whole thing work?” you may ask. Imagine we were writing a payment app. The code below would constitute a syntactically-valid Kotlin test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First sign into your console.
 Then check your point balance. There should be fifteen points.
 Then use all of your points to buy a ticket to Guam that costs exactly the number of points you have.
 Then check your point balance. It should now be zero.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kotlin makes the example above possible thanks to the infix keyword. I have provided below the same example with all of the infix functions needed to create syntactically correct Kotlin.&lt;/p&gt;

&lt;p&gt;You see that some functions above contain placeholder comments to verify the various bits of business logic that we are testing. This allows us to decouple the actual functions we are testing from their semantic meaning. It also reduces the ambiguity of intent even though it requires a fair amount of boilerplate. Even the boilerplate can be mitigated to a certain extent by scripts that transform prose into code.&lt;/p&gt;

&lt;p&gt;Robot tests are not the only situations where Kotlin-interpretable prose can prove useful. &lt;a href="https://try.kotlinlang.org/#/UserProjects/uspeu9cmn55b14jn71l3amlea1/r95i21of8ue2oc7aaop4rkp9dl" rel="noopener noreferrer"&gt;Devto articles work as well&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>Create a mock server for any REST API</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Thu, 06 Aug 2020 15:38:41 +0000</pubDate>
      <link>https://dev.to/meeshkan/create-a-mock-server-for-any-rest-api-592l</link>
      <guid>https://dev.to/meeshkan/create-a-mock-server-for-any-rest-api-592l</guid>
      <description>&lt;p&gt;If you make a REST API call from your codebase then there's a good chance that, at some point, you'll want to write a test for that integration. Instead of &lt;a href="https://dev.to/meeshkan/three-reasons-to-avoid-using-real-web-apis-in-your-integration-tests-1m3"&gt;calling the real API&lt;/a&gt;, it might make sense to use a mock. But manually stubbing data can be time-consuming and doesn't lead to a high level of confidence. &lt;/p&gt;

&lt;p&gt;That's where this tutorial comes in.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to create a mock server for any REST API. This mock server will generate dynamic, type-based response data that you can use in your tests. You'll do this using the &lt;a href="//https:github.com/meeshkan/hmt"&gt;HTTP Mocking Toolkit (HMT)&lt;/a&gt;, a tool that mocks HTTP APIs for use in automated and exploratory testing. &lt;/p&gt;

&lt;p&gt;As an example, this tutorial uses the &lt;a href="https://ghibliapi.herokuapp.com/"&gt;Studio Ghibli API&lt;/a&gt;, which catalogs the worlds created by Japanese anime studio &lt;a href="http://www.ghibli.jp/"&gt;Studio Ghibli&lt;/a&gt;. Why Studio Ghibli? Because they RULE! &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Steps&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Collect recordings of your API's traffic&lt;/li&gt;
&lt;li&gt;Build an OpenAPI specification from your recordings&lt;/li&gt;
&lt;li&gt;Mock server traffic using your specification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Prerequisites&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.python.org/downloads/"&gt;Python 3.6+&lt;/a&gt; installed (no previous Python knowledge is necessary, it's only for installing HMT)&lt;/li&gt;
&lt;li&gt;Familiarity with &lt;a href="https://www.programmableweb.com/api-university/what-are-apis-and-how-do-they-work"&gt;REST APIs&lt;/a&gt; and how they work&lt;/li&gt;
&lt;li&gt;Comfort using the &lt;a href="https://www.davidbaumgold.com/tutorials/command-line/"&gt;command-line&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💻 &lt;strong&gt;References&lt;/strong&gt;: &lt;br&gt;&lt;br&gt;
There's a &lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;GitHub repository&lt;/a&gt; that contains a completed Studio Ghibli mock server. You can use it as a reference for this tutorial. &lt;/p&gt;
&lt;h2&gt;
  
  
  Initial setup
&lt;/h2&gt;

&lt;p&gt;Before building the mock server, you first need to create a project directory. This will house your recordings and specifications (explained later in this tutorial).&lt;/p&gt;

&lt;p&gt;Let's do this in the terminal and name it &lt;code&gt;studio-ghibli-mock-server&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;studio-ghibli-mock-server
&lt;span class="nb"&gt;cd &lt;/span&gt;studio-ghibli-mock-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  (Optional) Create a virtual environment
&lt;/h3&gt;

&lt;p&gt;Using a &lt;a href="https://towardsdatascience.com/why-you-should-use-a-virtual-environment-for-every-python-project-c17dab3b0fd0"&gt;virtual environment&lt;/a&gt; can help keep your packages organized and ensure that you have the correct Python version. For this example, you'll name yours &lt;code&gt;.aichienv&lt;/code&gt; based on &lt;a href="https://www.japantimes.co.jp/news/2020/07/28/national/studio-ghibli-theme-park-construction/"&gt;the location of the new Studio Ghibli theme park&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;First, run the following script to set up a &lt;a href="https://docs.python.org/3/library/venv.html"&gt;venv&lt;/a&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .aichienv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, launch your virtual environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; .aichienv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, check your Python version with &lt;code&gt;python --version&lt;/code&gt;. It should be version 3.6 or higher.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever you're done, you can terminate the virtual environment by running: &lt;code&gt;deactivate&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Install HMT
&lt;/h3&gt;

&lt;p&gt;You can install HMT on the command line using &lt;a href="https://pip.pypa.io/en/stable/installing/"&gt;pip&lt;/a&gt;, a package installer for Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;hmt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For HMT to install and run properly, it &lt;strong&gt;requires Python version 3.6+&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check your HMT version with &lt;code&gt;hmt --version&lt;/code&gt; to make sure the command-line interface (CLI) is installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Collect recordings of your API's traffic
&lt;/h2&gt;

&lt;p&gt;The first step towards creating a mock server is to collect recordings of your API's traffic. That way, our future mock server will know what types of data to mimic.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;record&lt;/code&gt; mode, the HMT CLI can be used to record HTTP API traffic in a format that you can later build into a specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start HMT
&lt;/h3&gt;

&lt;p&gt;To start an HMT server that will record your API traffic, use the &lt;code&gt;hmt record&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt record
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts HMT as a reverse proxy on the default port of &lt;code&gt;8000&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To stop HMT without losing any of your data, type &lt;code&gt;Ctrl + C&lt;/code&gt; or another &lt;code&gt;kill&lt;/code&gt; command.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keep this running. Then, in another terminal window, you can use HMT as a proxy with &lt;a href="https://curl.haxx.se/"&gt;curl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By default, HMT uses path routing to intercept HTTP API calls. Path routing appends the URL you wish to call (&lt;code&gt;https://ghibliapi.herokuapp.com/&lt;/code&gt;) to the end of the URL of the recording server (&lt;code&gt;http://localhost:8000/&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/https://ghibliapi.herokuapp.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HMT will automatically make an API call using the URL in the path - in this case, &lt;code&gt;https://ghibliapi.herokuapp.com/&lt;/code&gt; - and return the response from the called API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run API-specific curl commands
&lt;/h3&gt;

&lt;p&gt;In order for HMT to later mock your API, it needs to understand what kinds of endpoints exist and the associated responses to expect. One way to feed it that information is by using curl.&lt;/p&gt;

&lt;p&gt;There's no minimum or maximum number of calls you should make in order for HMT to accurately record your API traffic. You have to feel it out. A general rule is that you want to record every critical endpoint at least once.&lt;/p&gt;

&lt;p&gt;With the Studio Ghibli API, there's five main endpoints: &lt;a href="https://ghibliapi.herokuapp.com/#tag/Films"&gt;Films&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/People"&gt;People&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/Locations"&gt;Locations&lt;/a&gt;, &lt;a href="https://ghibliapi.herokuapp.com/#tag/Species"&gt;Species&lt;/a&gt;, and &lt;a href="https://ghibliapi.herokuapp.com/#tag/Vehicles"&gt;Vehicles&lt;/a&gt;. You'll want to make sure to call each of those.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;The example in the reference repository&lt;/a&gt; alternates between calling the root endpoint and calling a specific field within that endpoint. For thoroughness, here's exactly what was tested:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Films&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/films

&lt;span class="c"&gt;# Film - Castle in the Sky&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/films/2baf70d1-42bb-4437-b551-e5fed5a87abe

&lt;span class="c"&gt;# People&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/people

&lt;span class="c"&gt;# Person - Granny (My Neighbor Totoro)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/people/08ffbce4-7f94-476a-95bc-76d3c3969c19

&lt;span class="c"&gt;# Locations&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/locations

&lt;span class="c"&gt;# Location - Irontown (Princess Mononoke)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/locations/11014596-71b0-4b3e-b8c0-1c4b15f28b9a

&lt;span class="c"&gt;# Species&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/species

&lt;span class="c"&gt;# Species - Cats&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/species/603428ba-8a86-4b0b-a9f1-65df6abef3d3

&lt;span class="c"&gt;# Vehicles&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/vehicles

&lt;span class="c"&gt;# Vehicle - Sōsuke's Boat (Ponyo on the Cliff by the Sea)&lt;/span&gt;
curl http://localhost:8000/https://ghibliapi.herokuapp.com/vehicles/923d70c9-8f15-4972-ad53-0128b261d628
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check the recordings file
&lt;/h3&gt;

&lt;p&gt;Running &lt;code&gt;hmt record&lt;/code&gt; will automatically generate two directories: &lt;code&gt;logs&lt;/code&gt; and &lt;code&gt;specs&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;By default, HMT records all traffic to the &lt;code&gt;logs&lt;/code&gt; directory in a file called &lt;code&gt;{hostname}-recordings.jsonl&lt;/code&gt;. &lt;code&gt;{hostname}&lt;/code&gt; refers to your API's host URL and in this case, that's &lt;code&gt;ghibliapi.herokuapp.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How it works is that HMT takes the recorded server traffic and serializes them as JSON objects in the &lt;a href="https://github.com/meeshkan/http-types"&gt;&lt;code&gt;http-types&lt;/code&gt;&lt;/a&gt; format. Then, this is written to a &lt;a href="http://jsonlines.org/"&gt;JSON Lines&lt;/a&gt; file. &lt;/p&gt;

&lt;p&gt;This specific formatting and file type is required for HMT to be able to build an OpenAPI specification in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Build an OpenAPI specification from your recordings
&lt;/h2&gt;

&lt;p&gt;Using the HMT CLI, you can build an &lt;a href="https://swagger.io/specification/"&gt;OpenAPI specification&lt;/a&gt; that describes how your API works. This is built from that &lt;code&gt;.jsonl&lt;/code&gt; file generated by the &lt;code&gt;record&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;On the command-line, you'll run &lt;code&gt;hmt build&lt;/code&gt; with the &lt;code&gt;--input-file&lt;/code&gt; flag followed by the path to your recordings file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt build &lt;span class="nt"&gt;--input-file&lt;/span&gt; logs/ghibliapi.herokuapp.com-recordings.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This uses the default build command. To see the other options, run &lt;code&gt;hmt build --help&lt;/code&gt; or check out the &lt;a href="https://github.com/meeshkan/hmt/blob/master/docs/BUILD.md"&gt;HMT build documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By default, HMT builds a new OpenAPI specification (called &lt;code&gt;openapi.json&lt;/code&gt;) in the &lt;code&gt;specs&lt;/code&gt; directory from earlier. Once you've generated the specification, you can use that to create a mock server.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Mock server traffic using your specification
&lt;/h2&gt;

&lt;p&gt;Now you can use your &lt;code&gt;openapi.json&lt;/code&gt; and a different HMT command to create a mock server. &lt;/p&gt;

&lt;p&gt;All it takes is &lt;code&gt;hmt mock&lt;/code&gt; followed by the path to the directory or file where your OpenAPI specification is (for this example, that's &lt;code&gt;specs/&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hmt mock specs/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep this running. Then, in another terminal window, make another curl request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/https://ghibliapi.herokuapp.com/people/08ffbce4-7f94-476a-95bc-76d3c3969c19
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Yes, you read that right - it's almost identical to the command that you ran earlier after launching &lt;code&gt;hmt record&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the same command we ran in the second step for Granny from My Neighbor Totoro. But our server won't return Granny's exact data. Instead, it'll return the same character response fields from the Studio Ghibli API with mock data for the values based on their types. &lt;/p&gt;

&lt;p&gt;Here's an example of what this response could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"Bradley Joseph"&lt;/span&gt;,
  &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Jeremy Vasquez"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"gender"&lt;/span&gt;: &lt;span class="s2"&gt;"Jodi Francis"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"age"&lt;/span&gt;: &lt;span class="s2"&gt;"Karen Booth"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"eye_color"&lt;/span&gt;: &lt;span class="s2"&gt;"Andre Mcclure"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"hair_color"&lt;/span&gt;: &lt;span class="s2"&gt;"Brandon Freeman"&lt;/span&gt;, 
  &lt;span class="s2"&gt;"films"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"Stephanie Campbell"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Paul Young"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Catherine Gonzalez DDS"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Charles Dean"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Jackson Smith"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Alexander Manning"&lt;/span&gt;, 
    &lt;span class="s2"&gt;"Anthony Reed"&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;, 
  &lt;span class="s2"&gt;"species"&lt;/span&gt;: &lt;span class="s2"&gt;"Jasmine Davis"&lt;/span&gt;,
  &lt;span class="s2"&gt;"url"&lt;/span&gt;: &lt;span class="s2"&gt;"David Olson"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Because this data is generated, there's a good chance that yours will be different if you're following along. Although the strings almost always seem to be random names 😅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There you have it, your very own mock server 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This tutorial ran through the entire HMT flow: &lt;strong&gt;Collect&lt;/strong&gt;, &lt;strong&gt;build&lt;/strong&gt;, and &lt;strong&gt;mock&lt;/strong&gt;. First, you collected data by recording server traffic from the Studio Ghibli API. Then, you built an OpenAPI specification based on that data. Finally, you used that specification to spin up a Studio Ghibli mock server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to see the code for the final mock server, check out the &lt;a href="https://github.com/meeshkan/studio-ghibli-mock-server"&gt;example repository on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are many customization options for your mock server - such as custom callback scripts, format options, and response types. You can find out more in the &lt;a href="https://github.com/meeshkan/hmt/blob/master/docs/MOCK.md"&gt;HMT documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;HMT is actively maintained by our team at Meeshkan. It's also open-source 🎉 If you run into any problems with the product or have questions, please &lt;a href="https://github.com/meeshkan/hmt/issues/new/choose"&gt;open an issue on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>testing</category>
      <category>api</category>
    </item>
    <item>
      <title>Finding and fixing bugs in your tests with fast-check</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Mon, 27 Jul 2020 13:59:20 +0000</pubDate>
      <link>https://dev.to/meeshkan/finding-and-fixing-bugs-in-your-tests-with-fast-check-5036</link>
      <guid>https://dev.to/meeshkan/finding-and-fixing-bugs-in-your-tests-with-fast-check-5036</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post assumes that you have a solid understanding of JavaScript. You should also know the basics of &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;property-based testing&lt;/a&gt; and the &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check framework&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recently, we published &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;Property-based testing for JavaScript developers&lt;/a&gt;. In it, we introduced &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2#what-your-existing-test-suite-probably-looks-like-and-is-missing"&gt;an issue to show the limitations of example-based testing&lt;/a&gt;. Throughout the rest of the guide, we provided examples of how to use fast-check and other property-based testing principles.&lt;/p&gt;

&lt;p&gt;But we didn't offer a fix to that initial testing bug.&lt;/p&gt;

&lt;p&gt;We've been told that this is unsatisfying, so consider this post our redemption.&lt;/p&gt;

&lt;p&gt;💻 The tests featured in this post are available in the &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/blob/main/tests/getNumberIntl.test.js"&gt;corresponding GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of the bug in our test
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're already familiar with the referenced issue, skip to the solution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine you have an input where users write in a price - but this input is &lt;code&gt;type="text"&lt;/code&gt; rather than &lt;code&gt;type="number"&lt;/code&gt;. So you need to create a function (&lt;code&gt;getNumber&lt;/code&gt;) that converts the input string into a number and an accompanying test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inputString&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;numberFromInputString&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&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 passes 🎉&lt;/p&gt;

&lt;p&gt;Now imagine your website also operates in Germany where the meaning of commas and decimals in numbers are switched (i.e. $1,200.99 in English would be $1.200,99 in German).&lt;/p&gt;

&lt;p&gt;So you add another test case to address this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns input string into a number&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// English test case&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;59.99&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// German test case&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;19,95&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;19.95&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;But when you run the test, you hit an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;expect&lt;span class="o"&gt;(&lt;/span&gt;received&lt;span class="o"&gt;)&lt;/span&gt;.toBe&lt;span class="o"&gt;(&lt;/span&gt;expected&lt;span class="o"&gt;)&lt;/span&gt; // Object.is equality

Expected: 19.95
Received: NaN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Assuming that your website and input are equipped to handle various locales and localized strings, this would be a limitation of your tests - not a bug in your app.&lt;/p&gt;

&lt;p&gt;There's something that can help though: &lt;strong&gt;Property-based testing&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing this bug with fast-check
&lt;/h2&gt;

&lt;p&gt;To solve this problem, let's use &lt;a href="https://dubzzz.github.io/fast-check/"&gt;fast-check&lt;/a&gt;, a JavaScript framework for generative test cases. Our goal is to test that our function turns any valid input string into a number, regardless of locale.&lt;/p&gt;

&lt;p&gt;First, we need to pick the &lt;strong&gt;property&lt;/strong&gt; (or properties) to test for in this situation. There a couple of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It works with strings that aren't formatted.&lt;/li&gt;
&lt;li&gt;It works with strings that are formatted using one of the accepted locales (in this case, that would be German).&lt;/li&gt;
&lt;li&gt;A combination of the two.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll tackle the latter: A combination of formatted and non-formatted strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spoiler alert: Final solution
&lt;/h3&gt;

&lt;p&gt;Here's a peek at what our test will look like by the end of this post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&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;fr-FR&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;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&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;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 a lot all at once. So let's go through it step-by-step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up our test
&lt;/h3&gt;

&lt;p&gt;To begin, we need to set up our test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;// Everything else will go here!&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This test uses the &lt;code&gt;assert&lt;/code&gt; and &lt;code&gt;property&lt;/code&gt; fast-check functions. If you need a refresher, these are both covered in our &lt;a href="https://dev.to/meeshkan/property-based-testing-for-javascript-developers-21b2"&gt;JavaScript property-based testing guide&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Applying our properties
&lt;/h3&gt;

&lt;p&gt;To test a combination of formatted and non-formatted strings, we need to pass two different arbitraries to &lt;code&gt;property&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first will be &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/float_1"&gt;&lt;code&gt;float&lt;/code&gt;&lt;/a&gt; to generate the floating-point numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The second is also a combination of sorts. To start, we need to write a &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/constantFrom_1"&gt;&lt;code&gt;constantFrom&lt;/code&gt; function&lt;/a&gt; that takes in multiple, equally probable values. We'll use this for our German locale: &lt;code&gt;de-DE&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="cm"&gt;/* This is where you'd pass another locale */&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then, we'll wrap &lt;code&gt;constantFrom&lt;/code&gt; in the &lt;a href="https://dubzzz.github.io/fast-check/#/2-API/fast-check/option_1"&gt;&lt;code&gt;option&lt;/code&gt; function&lt;/a&gt;. With &lt;code&gt;option&lt;/code&gt;, the complete arbitrary will return either &lt;code&gt;null&lt;/code&gt; (a stand-in for the English default) or our values from &lt;code&gt;constantFrom&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Prices in these locales only go to the second decimal place and we want to embody this in our test.&lt;/p&gt;

&lt;p&gt;To do this, we'll take the &lt;code&gt;testFloat&lt;/code&gt; value and use JavaScript's built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed"&gt;&lt;code&gt;toFixed&lt;/code&gt; method&lt;/a&gt; on it. The &lt;code&gt;2&lt;/code&gt; value indicates how many decimal places we want.&lt;/p&gt;

&lt;p&gt;This method returns a string, but we need a number for our final assertion. So we'll wrap it in another built-in function, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat"&gt;&lt;code&gt;parseFloat&lt;/code&gt;&lt;/a&gt;, and name this variable &lt;code&gt;fixedFloat&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we'll pass two arguments to the &lt;code&gt;property&lt;/code&gt; callback: &lt;code&gt;testFloat&lt;/code&gt; (representing each generated floating-point number) and &lt;code&gt;locale&lt;/code&gt; (representing the generated locale from our &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;constantFrom&lt;/code&gt; combination).&lt;/p&gt;

&lt;p&gt;Altogether, our &lt;code&gt;property&lt;/code&gt; function will look like this so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&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;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;// More to come!&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;h3&gt;
  
  
  Processing the strings
&lt;/h3&gt;

&lt;p&gt;Because we're testing both formatted and non-formatted strings, we need a way to differentiate these two string types.&lt;/p&gt;

&lt;p&gt;We'll create a variable called &lt;code&gt;floatString&lt;/code&gt; that checks if there is a &lt;code&gt;locale&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;locale !== null&lt;/code&gt;, then we need to create a localized string based on the generated float.&lt;/p&gt;

&lt;p&gt;To do this, we'll use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat"&gt;&lt;code&gt;Intl.NumberFormat&lt;/code&gt; constructor&lt;/a&gt; and pass in our &lt;code&gt;locale&lt;/code&gt; value. On top, we'll chain on the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/format"&gt;&lt;code&gt;format&lt;/code&gt; method&lt;/a&gt; with our &lt;code&gt;fixedFloat&lt;/code&gt; value from earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This constructor should mimic existing functionality in your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If &lt;code&gt;locale&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;, then we'll use the built-in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString"&gt;&lt;code&gt;toString&lt;/code&gt; method&lt;/a&gt; on &lt;code&gt;fixedFloat&lt;/code&gt;, which returns it as a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The resulting &lt;code&gt;floatString&lt;/code&gt; variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding your assertion
&lt;/h3&gt;

&lt;p&gt;At last, we need the most crucial part of any test: The assertion.&lt;/p&gt;

&lt;p&gt;The following &lt;a href="https://jestjs.io/docs/en/expect"&gt;&lt;code&gt;expect&lt;/code&gt; statement&lt;/a&gt; indicates that when you pass the &lt;code&gt;floatString&lt;/code&gt; (formatted or not) to the &lt;code&gt;getNumber&lt;/code&gt; function, you expect it to equal the &lt;code&gt;fixedFloat&lt;/code&gt; number value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;p&gt;After all that, you're back to that final result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;turns any valid input string into a number, regardless of locale&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constantFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de-DE&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;fr-FR&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;testFloat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;parseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;testFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;floatString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fixedFloat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;floatString&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixedFloat&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;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Reminder: You can check out the code in our &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs/blob/main/tests/getNumberIntl.test.js"&gt;accompanying GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now your tests are more thorough and resilient 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Special thanks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/dubzzz/"&gt;Nicolas Dubien&lt;/a&gt;, the creator of fast-check, was the first to flag this issue in the original guide. He also helped develop the solution. You're the best, Nicolas!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have a better solution? Comment below or &lt;a href="https://github.com/meeshkan/property-based-testing-for-js-devs"&gt;open a pull request&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>debugging</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Testing apps with third-party integrations</title>
      <dc:creator>Carolyn Stransky</dc:creator>
      <pubDate>Fri, 24 Jul 2020 15:31:32 +0000</pubDate>
      <link>https://dev.to/meeshkan/testing-apps-with-third-party-integrations-35m9</link>
      <guid>https://dev.to/meeshkan/testing-apps-with-third-party-integrations-35m9</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post assumes that you're familiar with &lt;a href="https://www.programmableweb.com/api-university/what-are-apis-and-how-do-they-work"&gt;APIs&lt;/a&gt; and have a basic understanding of testing. It's also based on a &lt;a href="https://www.youtube.com/watch?v=KFiSEQtTdpk&amp;amp;t=779s"&gt;presentation by Mike Solomon&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you’re working with the latest technologies or fighting against legacy code, you'll likely need to make a call to an API. And even more likely, this will be an API that you don't maintain.&lt;/p&gt;

&lt;p&gt;Reliance on external services is becoming more prevalent in our engineering ecosystem. As a result, we need cost-effective, secure, and reliable ways to test how our app interacts with these services.&lt;/p&gt;

&lt;p&gt;In this post, we'll examine some strategies and available tools for testing apps that use third-party integrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: If you don't have time to write tests but want to be sure your apps are covered, use an automated testing tool like Meeshkan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you test third-party integrations?
&lt;/h2&gt;

&lt;p&gt;The way we build apps has changed a lot in the past two decades. At the beginning of the 2000s, when you ran into a problem or needed a specific service, you had to build it yourself.&lt;/p&gt;

&lt;p&gt;Now, there's an API for almost everything. SendGrid for emails, Auth0 for authentication, Stripe for payments, and the list goes on. The &lt;a href="https://www.programmableweb.com/apis/directory"&gt;Programmable Web API Directory&lt;/a&gt; has over 23,000 different APIs available for use. Even &lt;a href="https://www.programmableweb.com/api/myspace-rest-api"&gt;MySpace has its own set of realtime REST APIs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But using a third-party integration that you didn't build and don't maintain is risky.&lt;/p&gt;

&lt;p&gt;You need to be sure that the calls you're making to these APIs are reliable and serving the expected data. That's why you should test them.&lt;/p&gt;

&lt;p&gt;There are a few different options for how to test these external services. Let’s start with the most common and walk-through some of the issues they can cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three common (but misguided) ways to test APIs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Do nothing
&lt;/h3&gt;

&lt;p&gt;Don't write tests - or comment them out when you write them and they don't work.&lt;/p&gt;

&lt;p&gt;If this is you, don't be ashamed.&lt;/p&gt;

&lt;p&gt;There's an entire economy around helping you solve issues that arise when you don't test your code. There are also products designed to test your apps when you understand the importance but don't want to manually write any (more on that later in this post).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Using the real APIs
&lt;/h3&gt;

&lt;p&gt;We have another blog post that highlights the &lt;a href="https://meeshkan.com/blog/why-not-use-real-apis-in-tests/"&gt;three primary reasons to not use the real APIs in tests&lt;/a&gt;. It covers security, integrity, and speed.&lt;/p&gt;

&lt;p&gt;But there are also lots of unfortunate scenarios that can happen when you use the real APIs in a &lt;a href="https://www.infoworld.com/article/3271126/what-is-cicd-continuous-integration-and-continuous-delivery-explained.html"&gt;CI/CD pipeline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During the research for his initial talk, Mike Solomon collected horror stories from developers who have used real APIs in their tests. Here are two of those.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I want you back”&lt;/strong&gt;&lt;br&gt;
One company accidentally embedded a Twilio API key in their CI environment. This caused some poor person in Kansas to receive dozens of text messages a day saying “I want you back &amp;lt;3”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;OR 1=1&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Another testing engineer created a fake username called &lt;code&gt;OR 1=1&lt;/code&gt; (a common &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/SQL_Injection"&gt;SQL injection&lt;/a&gt;). This username got sent repeatedly to a production API and the organization was banned from using the service.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Reverse engineering the API
&lt;/h3&gt;

&lt;p&gt;This option is the least dangerous, but the most time-consuming.&lt;/p&gt;

&lt;p&gt;When you create a reverse-engineered version of the API you're testing, it comes at a cost. For instance, sinking more time into writing a test script than you did the feature you're testing. Or the stubbed API data ends up being longer than the code you're testing. It's also difficult to maintain unless you endlessly monitor the changelog of that external API.&lt;/p&gt;

&lt;p&gt;None of these options are great, so let's look at more reliable strategies for testing your third-party integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Better ways to test third-party integrations
&lt;/h2&gt;

&lt;p&gt;It'd be cruel to leave you without a solution, so outlined below are two cost-effective, secure options for your tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write your tests with a mocking library
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;mock&lt;/strong&gt; is a substitute for a service that mimics the original functionality. Or at least the functionality that you're aiming to test.&lt;/p&gt;

&lt;p&gt;In this case, the mock acts as a replacement for your third-party integration. That way, you don't need to make a network call from your tests. This helps make your test resilient when the network is down or slow and enables you to specify and test corner cases. Plus mocks are often less complicated to access and maintain.&lt;/p&gt;

&lt;p&gt;There are some libraries you can use to write your mocks. We recently published a post &lt;a href="https://meeshkan.com/blog/unmock-vs-nock/"&gt;comparing two JavaScript mocking libraries - nock and unmock&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ve loved and used this approach ourselves (I mean, we built &lt;a href="https://github.com/meeshkan/unmock-js"&gt;unmock&lt;/a&gt;). There are still issues with this approach though. Namely, that you have to manually write all the tests - even if the input values are generated.&lt;/p&gt;

&lt;p&gt;This can be tedious and take a lot of time. So that’s where the second option comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a service (like Meeshkan) to test your apps
&lt;/h3&gt;

&lt;p&gt;Yes, this is a product plug - but with good reason.&lt;/p&gt;

&lt;p&gt;We built &lt;a href="https://meeshkan.com/"&gt;Meeshkan&lt;/a&gt; for those of you reading this post and wondering who has time to write tests. Our automated testing service executes and reports on a collection of generated tests. These tests are designed to imitate any third-party integrations you're working with using &lt;a href="https://meeshkan.com/docs/how-meeshkan-works/"&gt;schemas and a bit of NLP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All you need to do is authorize our GitHub app, choose a repository test, and set up your base configuration.&lt;/p&gt;

&lt;p&gt;Sound good? &lt;a href="https://meeshkan.com/"&gt;Request beta access today&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>api</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
