<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">Hi Carter,</p>
<p style="margin:0px 0px 1.2em!important">We are using <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">let !(#x,y#) = …</code> actually. Having the strict behaviour is not particularly difficult. You can even use <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">case … of (#x, y#) ->…</code> directly, it’s not too bad. My complaint, as it were, is solely about the potential for mistakes.</p>
<div title="MDH:PGRpdj5IaSBDYXJ0ZXIsPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5XZSBhcmUgdXNpbmcgYGxl
dCAhKCN4LHkjKSA9IOKApmAgYWN0dWFsbHkuIDxzcGFuIHpldW00YzE5PSJQUl8xXzAiIGRhdGEt
ZGRud2FiPSJQUl8xXzAiIGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj5IYXZp
bmcgdGhlIHN0cmljdDwvc3Bhbj4gYmVoYXZpb3VyIGlzIG5vdCBwYXJ0aWN1bGFybHkgZGlmZmlj
dWx0LiBZb3UgY2FuIGV2ZW4gdXNlIGBjYXNlIOKApiBvZiAoI3gsIHkjKSAtJmd0O+KApmAgZGly
ZWN0bHksIGl0J3Mgbm90IHRvbyBiYWQuIE15IGNvbXBsYWludCwgYXMgaXQgd2VyZSwgaXMgc29s
ZWx5IGFib3V0IHRoZSBwb3RlbnRpYWwgZm9yIG1pc3Rha2VzLjxicj48L2Rpdj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0"></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Aug 28, 2020 at 3:20 PM Carter Schonwald <<a href="mailto:carter.schonwald@gmail.com" target="_blank">carter.schonwald@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div dir="auto">Have you tried using do notation for bindings you want to keep strict, with Eg the identity monad? That doesn’t address the design critique but gives you a path forward ? </div></div><div dir="auto"><br></div><div dir="auto">I do agree that the semantics / default recursivity Of let bindings can be inappropriate for non recursive code , but would any other non uniform semantics or optimization be safe?</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Aug 28, 2020 at 9:05 AM Spiwack, Arnaud <<a href="mailto:arnaud.spiwack@tweag.io" target="_blank">arnaud.spiwack@tweag.io</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><p style="margin:0px 0px 1.2em">Dear all,</p><br><br><p style="margin:0px 0px 1.2em">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><br><br><p style="margin:0px 0px 1.2em">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" target="_blank">relevant section</a>:</p><br><br><blockquote style="margin:1.2em 0px;border-left:4px solid rgb(221,221,221);padding:0px 1em;color:rgb(119,119,119);quotes:none"><br><br><p style="margin:0px 0px 1.2em">You can have an unboxed tuple in a pattern binding, thus</p><br><br><pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%"><span style="color:rgb(153,0,0);font-weight:bold">f</span> x = <span style="color:rgb(51,51,51);font-weight:bold">let</span> (# p,q #) = h x <span style="color:rgb(51,51,51);font-weight:bold">in</span> ..body..<br><br></code></pre><br><br><p style="margin:0px 0px 1.2em">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><br><br><pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%"><span style="color:rgb(153,0,0);font-weight:bold">f</span> x = <span style="color:rgb(51,51,51);font-weight:bold">let</span> t = <span style="color:rgb(51,51,51);font-weight:bold">case</span> h x <span style="color:rgb(51,51,51);font-weight:bold">of</span> { (# p,q #) -> (p,q) }<br><br> p = fst t<br><br> q = snd t<br><br> <span style="color:rgb(51,51,51);font-weight:bold">in</span> ..body..<br><br></code></pre><br><br><p style="margin:0px 0px 1.2em">Indeed, the bindings can even be recursive.</p><br><br></blockquote><br><br><p style="margin:0px 0px 1.2em">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><br><br><pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);display:block;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%"><span style="color:rgb(153,0,0);font-weight:bold">let</span> u = hx<br><br><span style="color:rgb(153,0,0);font-weight:bold">in</span> ..body..<br><br></code></pre><br><br><p style="margin:0px 0px 1.2em">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><br><br><p style="margin:0px 0px 1.2em">I find that this behaviour invites trouble. But you may disagree. Let<br>me know!</p><br><br><div title="MDH:RGVhciBhbGwsPGJyPjxicj48c3BhbiB6ZXVtNGMxMD0iUFJfNTNfMCIgZGF0YS1kZG53YWI9IlBS<br><br>XzUzXzAiIGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj5JJ3ZlIGRpc2NvdmVy<br><br>ZWQ8L3NwYW4+IHRoZSBoYXJkIHdheSwgeWVzdGVyZGF5LCB0aGF0IDxzcGFuIHpldW00YzEwPSJQ<br><br>Ul81NF8wIiBkYXRhLWRkbndhYj0iUFJfNTRfMCIgYXJpYS1pbnZhbGlkPSJncmFtbWFyIiBjbGFz<br><br>cz0iTG0gbmciPmxhenkgbGV0IHBhdHRlcm48L3NwYW4+PGJyPm1hdGNoaW5nIGlzIGFsbG93ZWQg<br><br>b24gdW5ib3hlZCA8c3BhbiB6ZXVtNGMxMD0iUFJfNTVfMCIgZGF0YS1kZG53YWI9IlBSXzU1XzAi<br><br>IGFyaWEtaW52YWxpZD0iZ3JhbW1hciIgY2xhc3M9IkxtIG5nIj50dXBsZTwvc3Bhbj4uIEFuZCB0<br><br>aGF0IGl0IGltcGxpY2l0bHkgcmVib3hlczxicj50aGUgcGF0dGVybi48YnI+PGJyPkhlcmUgaXMg<br><br>aG93IHRoZSBtYW51YWwgZGVzY3JpYmVzIGl0LCBmcm9tIHRoZSBbcmVsZXZhbnQgc2VjdGlvbl1b<br><br>MV06PGJyPjxicj4mZ3Q7IFlvdSBjYW4gaGF2ZSBhbiB1bmJveGVkIHR1cGxlIGluIGEgcGF0dGVy<br><br>biBiaW5kaW5nLCB0aHVzPGJyPiZndDsgPGJyPiZndDsgYGBgaGFza2VsbDxicj4mZ3Q7IGYgeCA9<br><br>IGxldCAoIyBwLHEgIykgPSBoIHggaW4gLi5ib2R5Li48YnI+Jmd0OyBgYGA8YnI+Jmd0OyA8YnI+<br><br>Jmd0OyBJZiB0aGUgdHlwZXMgb2YgYHBgIGFuZCBgcWAgYXJlIG5vdCB1bmJveGVkLCB0aGUgcmVz<br><br>dWx0aW5nIGJpbmRpbmcgaXMgbGF6eSBsaWtlIGFueSBvdGhlciBIYXNrZWxsIHBhdHRlcm4gYmlu<br><br>ZGluZy4gVGhlIGFib3ZlIGV4YW1wbGUgZGVzdWdhcnMgbGlrZSB0aGlzOjxicj4mZ3Q7IDxicj4m<br><br>Z3Q7IDxicj4mZ3Q7IGBgYGhhc2tlbGw8YnI+Jmd0OyBmIHggPSBsZXQgdCA9IGNhc2UgaCB4IG9m<br><br>IHsgKCMgcCxxICMpIC0mZ3Q7IChwLHEpIH08YnI+Jmd0OyDCoCDCoCDCoCDCoCDCoCBwID0gZnN0<br><br>IHQ8YnI+Jmd0OyDCoCDCoCDCoCDCoCDCoCBxID0gPHNwYW4gemV1bTRjMTA9IlBSXzU2XzAiIGRh<br><br>dGEtZGRud2FiPSJQUl81Nl8wIiBhcmlhLWludmFsaWQ9InNwZWxsaW5nIiBjbGFzcz0iTEkgbmci<br><br>PnNuZDwvc3Bhbj4gdDxicj4mZ3Q7IMKgIMKgIMKgIGluIC4uYm9keS4uPGJyPiZndDsgYGBgPGJy<br><br>PiZndDsgPGJyPiZndDsgSW5kZWVkLCB0aGUgYmluZGluZ3MgY2FuIGV2ZW4gYmUgcmVjdXJzaXZl<br><br>Ljxicj48YnI+Tm90aWNlIGhvdyBgaCB4YCBpcyBsYXppbHkgYm91bmQsIGhlbmNlIHdvbid0IG5l<br><br>Y2Vzc2FyaWx5IGJlIHJ1biB3aGVuPGJyPmBib2R5YCBpcyBmb3JjZWQuIGFzIG9wcG9zZWQgdG8g<br><br>aWYgSSBoYWQgd3JpdHRlbiwgZm9yIGluc3RhbmNlLDxicj48YnI+YGBgaGFza2VsbDxicj5sZXQg<br><br>dSA9IGh4PGJyPmluIC4uYm9keS4uPGJyPmBgYDxicj48YnI+TXkgcXVlc3Rpb24gaXM6IGFyZSB3<br><br>ZSBoYXBweSB3aXRoIHRoaXM/IEkgZGlkIGZpbmQgdGhpcyBleHRyZW1lbHk8YnI+c3VycHJpc2lu<br><br>Zy4gSWYgSSdtIHVzaW5nIHVuYm94ZWQgdHVwbGVzLCBpdCdzIGJlY2F1c2UgSSB3YW50IHRvPGJy<br><br>Pmd1YXJhbnRlZSB0byBteXNlbGYgYSBzdHJpY3QsIHVuYm94ZWQgYmVoYXZpb3VyLiBCdXQgYSB2<br><br>ZXJ5IHN1YnRsZTxicj5zeW50YWN0aWMgZGV0YWlsIHNlZW1zIHRvIGJyZWFrIHRoaXMgZXhwZWN0<br><br>YXRpb24gZm9yIG1lLiBNeTxicj5leHBlY3RhdGlvbiB3b3VsZCBiZSB0aGF0IEkgd291bGQgbmVl<br><br>ZCB0byBleHBsaWNpdGx5IHJlYm94IHRoaW5nczxicj5iZWZvcmUgPHNwYW4gemV1bTRjMTA9IlBS<br><br>XzU3XzAiIGRhdGEtZGRud2FiPSJQUl81N18wIiBhcmlhLWludmFsaWQ9ImdyYW1tYXIiIGNsYXNz<br><br>PSJMbSBuZyI+dGhlPC9zcGFuPiBnZXQgbGF6eSBhZ2Fpbi48YnI+PGJyPkkgZmluZCB0aGF0IHRo<br><br>aXMgYmVoYXZpb3VyIGludml0ZXMgdHJvdWJsZS4gQnV0IHlvdSBtYXkgZGlzYWdyZWUuIExldDxi<br><br>cj5tZSBrbm93ITxicj48YnI+WzFdOiBodHRwczovL2Rvd25sb2Fkcy5oYXNrZWxsLm9yZy9naGMv<br><br>bGF0ZXN0L2RvY3MvaHRtbC91c2Vyc19ndWlkZS9nbGFzZ293X2V4dHMuaHRtbCNleHRlbnNpb24t<br><br>VW5ib3hlZFR1cGxlczxicj4=" style="height:0px;width:0px;max-height:0px;max-width:0px;overflow:hidden;font-size:0em;padding:0px;margin:0px"></div></div></div><br><br>_______________________________________________<br><br>ghc-devs mailing list<br><br><a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br><br><a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br><br></blockquote></div></div>
</blockquote></div>