<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">Hi all,</p>
<p style="margin:0px 0px 1.2em!important">Do we have already a syntax for ‘foo that also contains the typed value like TExp?</p>
<p style="margin:0px 0px 1.2em!important">I have e.g. an AST that I want to do more static checks on it that aren’t as convenient to do in the type system. Here’s an example:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">-- | Check the grammar spec to produce a grammar.</span>
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">checkGrammar</span> :: (<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">SchemaName</span>, [(<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">SchemaName</span>, <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Schema</span>)]) -> <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Q</span> <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Exp</span>
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">checkGrammar</span> (toplevel, rules) =
  <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">M</span>.size rulesMap /= length rules
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">then</span> error <span class="hljs-string" style="color:rgb(221,17,68)">"Duplicate rule names in grammar."</span>
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">else</span> lift (<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Grammar</span> {grammarToplevel = toplevel, grammarRules = rulesMap})
  <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">where</span>
    rulesMap = <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">M</span>.fromList rules

<span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">-- | Grammar for Haskell.</span>
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">grammar</span> :: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Grammar</span>
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">grammar</span> = $(checkGrammar $ runDefine $ <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">mdo</span>
  <span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">-- General expression</span>
  expression       <- rule <span class="hljs-string" style="color:rgb(221,17,68)">"Expression"</span> (<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">ChoiceSchema</span> [variable, constructor, parentheses
                                                      ,tuple, <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span>', application, string])
  application      <- rule <span class="hljs-string" style="color:rgb(221,17,68)">"Application"</span> (<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">CompositeSchema</span> [expression, expression])
  parentheses      <- rule <span class="hljs-string" style="color:rgb(221,17,68)">"Parentheses"</span> (<span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">CompositeSchema</span> [openParenSchema, expression, closeParenSchema])

...
 pure expression)
</code></pre>
<p style="margin:0px 0px 1.2em!important">Here I do a trivial check for duplicates. After I’ve checked the<br>expression at compile-time, I Lift it so that it can be used at<br>runtime. That’s pretty good. But some types like (a -> b) don’t Lift. So<br>an alternative would be:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">grammar</span> = $(checkGrammar_take2 thename 'thename)
</code></pre>
<p style="margin:0px 0px 1.2em!important">In which checkGrammar_take2 would:</p>
<ol style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">Use thename at compile-time for a check.</li>
<li style="margin:0.5em 0px">If the check passes, then return (VarE thename)</li>
</ol>
<p style="margin:0px 0px 1.2em!important">E.g.</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">checkGrammar_take2</span> value name = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> valueFine value <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">then</span> varE name <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">else</span>
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">error</span> <span class="hljs-string" style="color:rgb(221,17,68)">"value isn't fine"</span>
</code></pre>
<p style="margin:0px 0px 1.2em!important">That’s actually quite a good solution because it avoids a lift, and I<br>didn’t transform the AST. It’s also more efficient than lifting.</p>
<p style="margin:0px 0px 1.2em!important">But there’s no checked relationship between thename and ‘thename.<br>checkGrammar_take2 has no way of knowing that they refer to the same<br>thing. See?</p>
<p style="margin:0px 0px 1.2em!important">Hence, if I could get e.g. `thename to produce both the value and a<br>name for the value, that would be cool. My gist doesn’t go this<br>far. It might look like this:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">checkGrammar_take2</span> namedValue = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> valueFine (getValue namedValue) <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">then</span> getExp namedValue <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">else</span> error <span class="hljs-string" style="color:rgb(221,17,68)">"value isn't fine"</span>
</code></pre>
<p style="margin:0px 0px 1.2em!important">and call it like:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">mygrammar</span> = checkGrammar_take2 `thename
</code></pre>
<p style="margin:0px 0px 1.2em!important">So the semantics would be roughly similar to</p>
<p style="margin:0px 0px 1.2em!important">[|| thename ||] :: TExp a</p>
<p style="margin:0px 0px 1.2em!important">but you’d get</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)">`thename :: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Named</span> a
</code></pre>
<p style="margin:0px 0px 1.2em!important">where</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-haskell" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)"><span class="hljs-typedef"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">data</span> <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Named</span> a = <span class="hljs-container">{ <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">namedThing</span> :: <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">a</span>, <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">nameOfThing</span> :: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Name</span> }</span></span>
</code></pre>
<p style="margin:0px 0px 1.2em!important">I feel like the more DSLs I design, the more I’d like something like this to perform my static checks.</p>
<p style="margin:0px 0px 1.2em!important">Cheers,</p>
<p style="margin:0px 0px 1.2em!important">Chris</p>
<div title="MDH:SGkgYWxsLDxicj48YnI+RG8gd2UgaGF2ZSBhbHJlYWR5IGEgc3ludGF4IGZvciAnZm9vIHRoYXQg
YWxzbyBjb250YWlucyB0aGUgdHlwZWQgdmFsdWUgbGlrZSBURXhwPzxicj48YnI+SSBoYXZlIGUu
Zy4gYW4gQVNUIHRoYXQgSSB3YW50IHRvIGRvIG1vcmUgc3RhdGljIGNoZWNrcyBvbiBpdCB0aGF0
IGFyZW7igJl0IGFzIGNvbnZlbmllbnQgdG8gZG8gaW4gdGhlIHR5cGUgc3lzdGVtLiBIZXJl4oCZ
cyBhbiBleGFtcGxlOjxicj48YnI+YGBgaGFza2VsbDxicj4tLSB8IENoZWNrIHRoZSBncmFtbWFy
IHNwZWMgdG8gcHJvZHVjZSBhIGdyYW1tYXIuPGJyPmNoZWNrR3JhbW1hciA6OiAoU2NoZW1hTmFt
ZSwgWyhTY2hlbWFOYW1lLCBTY2hlbWEpXSkgLSZndDsgUSBFeHA8YnI+Y2hlY2tHcmFtbWFyICh0
b3BsZXZlbCwgcnVsZXMpID08YnI+wqAgaWYgTS5zaXplIHJ1bGVzTWFwIC89IGxlbmd0aCBydWxl
czxicj7CoCDCoCB0aGVuIGVycm9yICJEdXBsaWNhdGUgcnVsZSBuYW1lcyBpbiBncmFtbWFyLiI8
YnI+wqAgwqAgZWxzZSBsaWZ0IChHcmFtbWFyIHtncmFtbWFyVG9wbGV2ZWwgPSB0b3BsZXZlbCwg
Z3JhbW1hclJ1bGVzID0gcnVsZXNNYXB9KTxicj7CoCB3aGVyZTxicj7CoCDCoCBydWxlc01hcCA9
IE0uZnJvbUxpc3QgcnVsZXM8YnI+PGJyPi0tIHwgR3JhbW1hciBmb3IgSGFza2VsbC48YnI+Z3Jh
bW1hciA6OiBHcmFtbWFyPGJyPmdyYW1tYXIgPSAkKGNoZWNrR3JhbW1hciAkIHJ1bkRlZmluZSAk
IG1kbzxicj7CoCAtLSBHZW5lcmFsIGV4cHJlc3Npb248YnI+wqAgZXhwcmVzc2lvbiDCoCDCoCDC
oCAmbHQ7LSBydWxlICJFeHByZXNzaW9uIiAoQ2hvaWNlU2NoZW1hIFt2YXJpYWJsZSwgY29uc3Ry
dWN0b3IsIHBhcmVudGhlc2VzPGJyPsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg
IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgICx0dXBsZSwgbGV0
JywgYXBwbGljYXRpb24sIHN0cmluZ10pPGJyPsKgIGFwcGxpY2F0aW9uIMKgIMKgIMKgJmx0Oy0g
cnVsZSAiQXBwbGljYXRpb24iIChDb21wb3NpdGVTY2hlbWEgW2V4cHJlc3Npb24sIGV4cHJlc3Np
b25dKTxicj7CoCBwYXJlbnRoZXNlcyDCoCDCoCDCoCZsdDstIHJ1bGUgIlBhcmVudGhlc2VzIiAo
Q29tcG9zaXRlU2NoZW1hIFtvcGVuUGFyZW5TY2hlbWEsIGV4cHJlc3Npb24sIGNsb3NlUGFyZW5T
Y2hlbWFdKTxicj48YnI+Li4uPGJyPsKgcHVyZSBleHByZXNzaW9uKTxicj5gYGA8YnI+PGJyPkhl
cmUgSSBkbyBhIHRyaXZpYWwgY2hlY2sgZm9yIGR1cGxpY2F0ZXMuIEFmdGVyIEnigJl2ZSBjaGVj
a2VkIHRoZTxicj5leHByZXNzaW9uIGF0IGNvbXBpbGUtdGltZSwgSSBMaWZ0IGl0IHNvIHRoYXQg
aXQgY2FuIGJlIHVzZWQgYXQ8YnI+cnVudGltZS4gVGhhdOKAmXMgcHJldHR5IGdvb2QuIEJ1dCBz
b21lIHR5cGVzIGxpa2UgKGEgLSZndDsgYikgZG9u4oCZdCBMaWZ0LiBTbzxicj5hbiBhbHRlcm5h
dGl2ZSB3b3VsZCBiZTo8YnI+PGJyPmBgYCBoYXNrZWxsPGJyPmdyYW1tYXIgPSAkKGNoZWNrR3Jh
bW1hcl90YWtlMiB0aGVuYW1lICd0aGVuYW1lKTxicj5gYGA8YnI+PGJyPkluIHdoaWNoIGNoZWNr
R3JhbW1hcl90YWtlMiB3b3VsZDo8YnI+PGJyPjEuIFVzZSB0aGVuYW1lIGF0IGNvbXBpbGUtdGlt
ZSBmb3IgYSBjaGVjay48YnI+Mi4gSWYgdGhlIGNoZWNrIHBhc3NlcywgdGhlbiByZXR1cm4gKFZh
ckUgdGhlbmFtZSk8YnI+PGJyPjxkaXY+RS5nLjxicj48YnI+YGBgIGhhc2tlbGw8YnI+Y2hlY2tH
cmFtbWFyX3Rha2UyIHZhbHVlIG5hbWUgPSBpZiB2YWx1ZUZpbmUgdmFsdWUgdGhlbiB2YXJFIG5h
bWUgZWxzZTxicj5lcnJvciAidmFsdWUgaXNuJ3QgZmluZSI8YnI+YGBgPGJyPjxicj5UaGF04oCZ
cyBhY3R1YWxseSBxdWl0ZSBhIGdvb2Qgc29sdXRpb24gYmVjYXVzZSBpdCBhdm9pZHMgYSBsaWZ0
LCBhbmQgSTxicj5kaWRu4oCZdCB0cmFuc2Zvcm0gdGhlIEFTVC4gSXQncyBhbHNvIG1vcmUgZWZm
aWNpZW50IHRoYW4gbGlmdGluZy48YnI+PGJyPkJ1dCB0aGVyZeKAmXMgbm8gY2hlY2tlZCByZWxh
dGlvbnNoaXAgYmV0d2VlbiB0aGVuYW1lIGFuZCDigJh0aGVuYW1lLjxicj5jaGVja0dyYW1tYXJf
dGFrZTIgaGFzIG5vIHdheSBvZiBrbm93aW5nIHRoYXQgdGhleSByZWZlciB0byB0aGUgc2FtZTxi
cj50aGluZy4gU2VlPzxicj48YnI+SGVuY2UsIGlmIEkgY291bGQgZ2V0IGUuZy4gYHRoZW5hbWUg
dG8gcHJvZHVjZSBib3RoIHRoZSB2YWx1ZSBhbmQgYTxicj5uYW1lIGZvciB0aGUgdmFsdWUsIHRo
YXQgd291bGQgYmUgY29vbC4gTXkgZ2lzdCBkb2VzbuKAmXQgZ28gdGhpczxicj5mYXIuIEl0IG1p
Z2h0IGxvb2sgbGlrZSB0aGlzOjxicj48YnI+YGBgIGhhc2tlbGw8YnI+Y2hlY2tHcmFtbWFyX3Rh
a2UyIG5hbWVkVmFsdWUgPSBpZiB2YWx1ZUZpbmUgKGdldFZhbHVlIG5hbWVkVmFsdWUpIHRoZW4g
Z2V0RXhwIG5hbWVkVmFsdWUgZWxzZSBlcnJvciAidmFsdWUgaXNuJ3QgZmluZSI8YnI+YGBgPGJy
Pjxicj5hbmQgY2FsbCBpdCBsaWtlOjxicj48YnI+YGBgIGhhc2tlbGw8YnI+bXlncmFtbWFyID0g
Y2hlY2tHcmFtbWFyX3Rha2UyIGB0aGVuYW1lPGJyPmBgYDxicj48YnI+U28gdGhlIHNlbWFudGlj
cyB3b3VsZCBiZSByb3VnaGx5IHNpbWlsYXIgdG88YnI+PGJyPlt8fCB0aGVuYW1lIHx8XSA6OiBU
RXhwIGE8YnI+PGJyPmJ1dCB5b3UnZCBnZXQ8YnI+PGJyPmBgYCBoYXNrZWxsPGJyPmB0aGVuYW1l
IDo6IE5hbWVkIGE8YnI+YGBgPGJyPjxicj53aGVyZTxicj48YnI+YGBgaGFza2VsbDxicj5kYXRh
IE5hbWVkIGEgPSB7IG5hbWVkVGhpbmcgOjogYSwgbmFtZU9mVGhpbmcgOjogTmFtZSB9PGJyPmBg
YDxicj48YnI+SSBmZWVsIGxpa2UgdGhlIG1vcmUgRFNMcyBJIGRlc2lnbiwgdGhlIG1vcmUgSeKA
mWQgbGlrZSBzb21ldGhpbmcgbGlrZSB0aGlzIHRvIHBlcmZvcm0gbXkgc3RhdGljIGNoZWNrcy48
YnI+PGJyPkNoZWVycyw8YnI+PGJyPkNocmlzPGJyPjwvZGl2Pg==" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0"></div></div></div>