<div dir="ltr"><h1 style="font-weight:normal;color:rgb(17,17,17);line-height:1em;font-size:2.5em;font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif">
Anonymous records. A solution to the problems of record-system.</h1><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
The current record system is notorious for three major flaws:</p><ol style="margin:1em 0px;padding:0px 0px 0px 2em;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<li><p style="margin:1em 0px">It does not solve the namespacing problem. I.e., you cannot have two records sharing field names in a single module. E.g., the following won't compile:</p><div class=""><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">data</span> <span class="">A</span> <span class="">=</span> <span class="">A</span> <span class="">{</span> <span class="">field</span> <span class="">::</span> <span class="">String</span> <span class="">}</span>
<span class="">data</span> <span class="">B</span> <span class="">=</span> <span class="">B</span> <span class="">{</span> <span class="">field</span> <span class="">::</span> <span class="">String</span> <span class="">}</span>
</pre></div></li><li><p style="margin:1em 0px">It's partial. The following code will result in a runtime error:</p><div class=""><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">data</span> <span class="">A</span> <span class="">=</span> <span class="">A1</span> <span class="">{</span> <span class="">field1</span> <span class="">::</span> <span class="">String</span> <span class="">}</span> <span class="">|</span> <span class="">A2</span> <span class="">{</span> <span class="">field2</span> <span class="">::</span> <span class="">String</span> <span class="">}</span>

<span class="">main</span> <span class="">=</span> <span class="">print</span> <span class="">$</span> <span class="">field1</span> <span class="">$</span> <span class="">A2</span> <span class="">"abc"</span>
</pre></div></li><li><p style="margin:1em 0px">It does not allow you to use the same field name for different types across constructors:</p><div class=""><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">data</span> <span class="">A</span> <span class="">=</span> <span class="">A1</span> <span class="">{</span> <span class="">field</span> <span class="">::</span> <span class="">String</span> <span class="">}</span> <span class="">|</span> <span class="">A2</span> <span class="">{</span> <span class="">field</span> <span class="">::</span> <span class="">Int</span> <span class="">}</span>
</pre></div></li></ol><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
This proposal approaches all the problems above and also a fourth one, which is unrelated to the current record system: it allows one to avoid declaration of intermediate types (see details below).</p><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
Gentlemen, I want you to meet,</p><h2 style="font-weight:normal;color:rgb(17,17,17);line-height:1em;font-size:2em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:silver;padding-bottom:5px;font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif">
<a name="anonymous-records" class="" href="#anonymous-records" style="color:rgb(11,0,128);text-decoration:none"><span class=""></span></a>Anonymous Records</h2><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
When a record-syntax is used in Haskell it's almost always a single-constructor ADT. A question rises then: why use ADT when you don't need its main feature (i.e., the multiple constructors)? This main feature is actually the root of the second and the third problem of record-syntax from the list above. In such situations one doesn't actually need ADT, but something more like a tuple with ability to access its items by name. E.g.:</p>
<div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px"><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">f</span> <span class="">::</span> <span class="">(</span><span class="">a</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">b</span> <span class="">::</span> <span class="">String</span><span class="">)</span> <span class="">-></span> <span class="">String</span>
<span class="">f</span> <span class="">rec</span> <span class="">=</span> <span class="">rec</span><span class="">.</span><span class="">b</span> <span class="">++</span> <span class="">show</span> <span class="">rec</span><span class="">.</span><span class="">a</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
application:</p><div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">f</span> <span class="">(</span><span class="">a</span> <span class="">=</span> <span class="">123</span><span class="">,</span> <span class="">b</span> <span class="">=</span> <span class="">"abc"</span><span class="">)</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
So now you think "Okay, but how about naming it?". Well, not a problem at all - use the existing<code style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);padding:0px 3px">type</code>-construct:</p>
<div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px"><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">type</span> <span class="">TheRecord</span> <span class="">=</span> <span class="">(</span><span class="">a</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">b</span> <span class="">::</span> <span class="">String</span><span class="">)</span> 
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
Now, about the avoidance of intermediate types:</p><div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">type</span> <span class="">Person</span> <span class="">=</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">(</span><span class="">country</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">area</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">number</span> <span class="">::</span> <span class="">Int</span><span class="">))</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
See? No need to declare separate types for inner values. But, of course, if you need, you still can:</p><div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">type</span> <span class="">Phone</span> <span class="">=</span> <span class="">(</span><span class="">country</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">area</span> <span class="">::</span> <span class="">Int</span><span class="">,</span> <span class="">number</span> <span class="">::</span> <span class="">Int</span><span class="">)</span>
<span class="">type</span> <span class="">Person</span> <span class="">=</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">Phone</span><span class="">)</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
We can nicely access the deeply nested fields, e.g.:</p><div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">personCountryCode</span> <span class="">::</span> <span class="">Person</span> <span class="">-></span> <span class="">Int</span>
<span class="">personCountryCode</span> <span class="">person</span> <span class="">=</span> <span class="">person</span><span class="">.</span><span class="">phone</span><span class="">.</span><span class="">country</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
Okay. What about the type ambiguity? E.g., in the following the <code style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);padding:0px 3px">Person</code> is actually the same type as<code style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);padding:0px 3px">Company</code>:</p>
<div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px"><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">type</span> <span class="">Person</span> <span class="">=</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">Phone</span><span class="">)</span>
<span class="">type</span> <span class="">Company</span> <span class="">=</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">Phone</span><span class="">)</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
Easily solvable with a help of <code style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);padding:0px 3px">newtype</code>:</p>
<div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px"><pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">newtype</span> <span class="">Person</span> <span class="">=</span> <span class="">Person</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">Phone</span><span class="">)</span>
<span class="">newtype</span> <span class="">Company</span> <span class="">=</span> <span class="">Company</span> <span class="">(</span><span class="">name</span> <span class="">::</span> <span class="">String</span><span class="">,</span> <span class="">phone</span> <span class="">::</span> <span class="">Phone</span><span class="">)</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
What about ADTs? Again, easy:</p><div class="" style="color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<pre style="color:rgb(0,0,0);font-size:0.88em;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;background-color:rgb(248,248,248);border:1px solid rgb(204,204,204);white-space:pre-wrap;word-wrap:break-word;padding:5px 12px">
<span class="">data</span> <span class="">Product</span> <span class="">=</span> <span class="">Tea</span> <span class="">(</span><span class="">brand</span> <span class="">::</span> <span class="">Company</span><span class="">)</span>
             <span class="">|</span> <span class="">Milk</span> <span class="">(</span><span class="">brand</span> <span class="">::</span> <span class="">Company</span><span class="">,</span> <span class="">fatness</span> <span class="">::</span> <span class="">Float</span><span class="">)</span>
</pre></div><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
Now, the beautiful fact:</p><p style="margin:1em 0px;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
This solution does not conflict with any existing feature of Haskell! As the examples show, it easily fits into the language as an extension. It can peacefully coexist with the existing record system of ADTs. Hence a complete backwards compatibility with old codebase. There's also a potential for many other additional features.</p>
<h2 style="font-weight:normal;color:rgb(17,17,17);line-height:1em;font-size:2em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:silver;padding-bottom:5px;font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif">
<a name="links" class="" href="#links" style="color:rgb(11,0,128);text-decoration:none"><span class=""></span></a>Links</h2><ul style="margin:1em 0px;padding:0px 0px 0px 2em;color:rgb(68,68,68);font-family:Georgia,Palatino,'Palatino Linotype',Times,'Times New Roman','Hiragino Sans GB',STXihei,微软雅黑,serif;font-size:16px;line-height:24px">
<li><a href="https://gist.github.com/nikita-volkov/6977841" style="color:rgb(11,0,128);text-decoration:none">Source of this proposal</a>.</li></ul></div>