title: How to implement sum types in dynamically typed languages without pattern matching
body: <p>I have only a theoretical idea of Haskell's sum types. And yet I sense that they really matter in Haskell and change the way you model your data in a fundamental way. Since I believe that they can be useful in dynamically typed languages as well, I tried to implement a sensible approximation in Javascript (I have only a superficial knowledge of Haskell).</p>
  
  <p>Here is a more or less useful example of a <code>Name</code> sum type, that is able to handle various name formats. I know that Haskell distinguishes between type and data constructors and probably has good reasons to make such distinction. However, I guess that it is not possible to map this concept to Javascript. And pattern matching neither.</p>
  
  <p>Anyway, my actual question is: Does the following implementation embody the nature of sum types and the way they are applied in Haskell?</p>
  
  <p>Please note: I am not sure if this kind of cross-language questions are welcome on SO. Please let me know in case I should avoid them.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>// auxiliary functions
  
  const A = f =&gt; x =&gt; f(x);
  const show = api =&gt; api.show;
  
  // the type constructor
  
  const Name = (...xs) =&gt; A(({length: len}) =&gt; {
    switch (len) {
      case 1: {
        let [{length: len}] = xs; // no pattern matching but destructuring
  
        if (len &gt; 1) { // no Char type in JS
          return k =&gt; k({show: () =&gt; xs[0]}); // returns the API
        }
  
        break;
      }
  
      case 2: {
        let [{length: len}, {length: len2}] = xs;
  
        if (len &gt; 1 &amp;&amp; len2 &gt; 1) {
          return k =&gt; k({show: () =&gt; `${xs[0]} ${xs[1]}`});
        }
  
        if (len === 1 &amp;&amp; len2 &gt; 1) {
          return k =&gt; k({show: () =&gt; `${xs[0]}. ${xs[1]}`});
        }
  
        break;
      }
  
      case 3: {
        let [{length: len}, {length: len2}, {length: len3}] = xs;
  
        if (len &gt; 1 &amp;&amp; len2 &gt; 1 &amp;&amp; len3 &gt; 1) {
          return k =&gt; k({show: () =&gt; `${xs[0]} ${xs[1]} ${xs[2]}`});
        }
  
        if (len &gt; 1 &amp;&amp; len2 === 1 &amp;&amp; len3 &gt; 1) {
          return k =&gt; k({show: () =&gt; `${xs[0]} ${xs[1]}. ${xs[2]}`});
        }
  
        if (len === 1 &amp;&amp; len2 === 1 &amp;&amp; len3 &gt; 1) {
          return k =&gt; k({show: () =&gt; `${xs[0]}. ${xs[1]}. ${xs[2]}`});
        }
      }
  
      default: throw new TypeError();
    }
  }) (xs);
  
  // run
  
  console.log(Name("Kerouac") (show) ());
  console.log(Name("Hans", "Hölzel") (show) ());
  console.log(Name("H", "Curry") (show) ());
  console.log(Name("Jean", "Luc", "Godard") (show) ());
  console.log(Name("William", "S", "Burroughs") (show) ());
  console.log(Name("E", "W", "Dijkstra") (show) ());</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>[EDIT]</strong></p>
  
  <p>Sorry, I should have provided some Haskell code:</p>
  
  <pre><code>type FirstName = String
  type LastName = String
  type MiddleName = String
  
  data Name = FullName FirstName LastName
    | NameWithMiddle FirstName MiddleName LastName
    | NameWithMiddleInitial FirstName Char LastName
    | TwoInitialsWithLast Char Char LastName
    | OneInitialWithLast Char LastName
    | LastNameOnly LastName
  </code></pre>
  
  <p>I am not sure if this is valid though.</p>
  
  <p>I guess the problem with my approach is that I try to implement the type constructor <code>Name</code>, while I should implement the value constructors, right?</p>