<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">Dear all,</p>
<p style="margin:0px 0px 1.2em!important">I discovered the hard way, yesterday, that lazy let pattern<br>matching is allowed on unboxed tuples. And that it implicitly reboxes<br>the pattern.</p>
<p style="margin:0px 0px 1.2em!important">Here is how the manual describes it, from the <a href="https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#extension-UnboxedTuples">relevant section</a>:</p>
<blockquote style="margin:1.2em 0px;border-left:4px solid rgb(221,221,221);padding:0px 1em;color:rgb(119,119,119);quotes:none">
<p style="margin:0px 0px 1.2em!important">You can have an unboxed tuple in a pattern binding, thus</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) none repeat scroll 0% 0%"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">f</span> x = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> (# p,q #) = h x <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">in</span> ..body..
</code></pre>
<p style="margin:0px 0px 1.2em!important">If the types of <code 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">p</code> and <code 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">q</code> are not unboxed, the resulting binding is lazy like any other Haskell pattern binding. The above example desugars 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) none repeat scroll 0% 0%"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">f</span> x = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> t = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">case</span> h x <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">of</span> { (# p,q #) -> (p,q) }
          p = fst t
          q = snd t
      <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">in</span> ..body..
</code></pre>
<p style="margin:0px 0px 1.2em!important">Indeed, the bindings can even be recursive.</p>
</blockquote>
<p style="margin:0px 0px 1.2em!important">Notice how <code 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">h x</code> is lazily bound, hence won’t necessarily be run when<br><code 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">body</code> is forced. as opposed to if I had written, for instance,</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) none repeat scroll 0% 0%"><span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">let</span> u = hx
<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">in</span> ..body..
</code></pre>
<p style="margin:0px 0px 1.2em!important">My question is: are we happy with this? I did find this extremely<br>surprising. If I’m using unboxed tuples, it’s because I want to<br>guarantee to myself a strict, unboxed behaviour. But a very subtle<br>syntactic detail seems to break this expectation for me. My<br>expectation would be that I would need to explicitly rebox things<br>before they get lazy again.</p>
<p style="margin:0px 0px 1.2em!important">I find that this behaviour invites trouble. But you may disagree. Let<br>me know!</p>
<div title="MDH:RGVhciBhbGwsPGJyPjxicj48c3BhbiB6ZXVtNGMxMD0iUFJfNTNfMCIgZGF0YS1kZG53YWI9IlBS
XzUzXzAiIGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj5JJ3ZlIGRpc2NvdmVy
ZWQ8L3NwYW4+IHRoZSBoYXJkIHdheSwgeWVzdGVyZGF5LCB0aGF0IDxzcGFuIHpldW00YzEwPSJQ
Ul81NF8wIiBkYXRhLWRkbndhYj0iUFJfNTRfMCIgYXJpYS1pbnZhbGlkPSJncmFtbWFyIiBjbGFz
cz0iTG0gbmciPmxhenkgbGV0IHBhdHRlcm48L3NwYW4+PGJyPm1hdGNoaW5nIGlzIGFsbG93ZWQg
b24gdW5ib3hlZCA8c3BhbiB6ZXVtNGMxMD0iUFJfNTVfMCIgZGF0YS1kZG53YWI9IlBSXzU1XzAi
IGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj50dXBsZTwvc3Bhbj4uIEFuZCB0
aGF0IGl0IGltcGxpY2l0bHkgcmVib3hlczxicj50aGUgcGF0dGVybi48YnI+PGJyPkhlcmUgaXMg
aG93IHRoZSBtYW51YWwgZGVzY3JpYmVzIGl0LCBmcm9tIHRoZSBbcmVsZXZhbnQgc2VjdGlvbl1b
MV06PGJyPjxicj4mZ3Q7IFlvdSBjYW4gaGF2ZSBhbiB1bmJveGVkIHR1cGxlIGluIGEgcGF0dGVy
biBiaW5kaW5nLCB0aHVzPGJyPiZndDsgPGJyPiZndDsgYGBgaGFza2VsbDxicj4mZ3Q7IGYgeCA9
IGxldCAoIyBwLHEgIykgPSBoIHggaW4gLi5ib2R5Li48YnI+Jmd0OyBgYGA8YnI+Jmd0OyA8YnI+
Jmd0OyBJZiB0aGUgdHlwZXMgb2YgYHBgIGFuZCBgcWAgYXJlIG5vdCB1bmJveGVkLCB0aGUgcmVz
dWx0aW5nIGJpbmRpbmcgaXMgbGF6eSBsaWtlIGFueSBvdGhlciBIYXNrZWxsIHBhdHRlcm4gYmlu
ZGluZy4gVGhlIGFib3ZlIGV4YW1wbGUgZGVzdWdhcnMgbGlrZSB0aGlzOjxicj4mZ3Q7IDxicj4m
Z3Q7IDxicj4mZ3Q7IGBgYGhhc2tlbGw8YnI+Jmd0OyBmIHggPSBsZXQgdCA9IGNhc2UgaCB4IG9m
IHsgKCMgcCxxICMpIC0mZ3Q7IChwLHEpIH08YnI+Jmd0OyDCoCDCoCDCoCDCoCDCoCBwID0gZnN0
IHQ8YnI+Jmd0OyDCoCDCoCDCoCDCoCDCoCBxID0gPHNwYW4gemV1bTRjMTA9IlBSXzU2XzAiIGRh
dGEtZGRud2FiPSJQUl81Nl8wIiBhcmlhLWludmFsaWQ9InNwZWxsaW5nIiBjbGFzcz0iTEkgbmci
PnNuZDwvc3Bhbj4gdDxicj4mZ3Q7IMKgIMKgIMKgIGluIC4uYm9keS4uPGJyPiZndDsgYGBgPGJy
PiZndDsgPGJyPiZndDsgSW5kZWVkLCB0aGUgYmluZGluZ3MgY2FuIGV2ZW4gYmUgcmVjdXJzaXZl
Ljxicj48YnI+Tm90aWNlIGhvdyBgaCB4YCBpcyBsYXppbHkgYm91bmQsIGhlbmNlIHdvbid0IG5l
Y2Vzc2FyaWx5IGJlIHJ1biB3aGVuPGJyPmBib2R5YCBpcyBmb3JjZWQuIGFzIG9wcG9zZWQgdG8g
aWYgSSBoYWQgd3JpdHRlbiwgZm9yIGluc3RhbmNlLDxicj48YnI+YGBgaGFza2VsbDxicj5sZXQg
dSA9IGh4PGJyPmluIC4uYm9keS4uPGJyPmBgYDxicj48YnI+TXkgcXVlc3Rpb24gaXM6IGFyZSB3
ZSBoYXBweSB3aXRoIHRoaXM/IEkgZGlkIGZpbmQgdGhpcyBleHRyZW1lbHk8YnI+c3VycHJpc2lu
Zy4gSWYgSSdtIHVzaW5nIHVuYm94ZWQgdHVwbGVzLCBpdCdzIGJlY2F1c2UgSSB3YW50IHRvPGJy
Pmd1YXJhbnRlZSB0byBteXNlbGYgYSBzdHJpY3QsIHVuYm94ZWQgYmVoYXZpb3VyLiBCdXQgYSB2
ZXJ5IHN1YnRsZTxicj5zeW50YWN0aWMgZGV0YWlsIHNlZW1zIHRvIGJyZWFrIHRoaXMgZXhwZWN0
YXRpb24gZm9yIG1lLiBNeTxicj5leHBlY3RhdGlvbiB3b3VsZCBiZSB0aGF0IEkgd291bGQgbmVl
ZCB0byBleHBsaWNpdGx5IHJlYm94IHRoaW5nczxicj5iZWZvcmUgPHNwYW4gemV1bTRjMTA9IlBS
XzU3XzAiIGRhdGEtZGRud2FiPSJQUl81N18wIiBhcmlhLWludmFsaWQ9ImdyYW1tYXIiIGNsYXNz
PSJMbSBuZyI+dGhlPC9zcGFuPiBnZXQgbGF6eSBhZ2Fpbi48YnI+PGJyPkkgZmluZCB0aGF0IHRo
aXMgYmVoYXZpb3VyIGludml0ZXMgdHJvdWJsZS4gQnV0IHlvdSBtYXkgZGlzYWdyZWUuIExldDxi
cj5tZSBrbm93ITxicj48YnI+WzFdOiBodHRwczovL2Rvd25sb2Fkcy5oYXNrZWxsLm9yZy9naGMv
bGF0ZXN0L2RvY3MvaHRtbC91c2Vyc19ndWlkZS9nbGFzZ293X2V4dHMuaHRtbCNleHRlbnNpb24t
VW5ib3hlZFR1cGxlczxicj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0"></div></div></div>