<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="markdown-here-wrapper" data-md-url="Thunderbird"
      style="font-family: Ubuntu,Cantarell,Deja Vu Sans,sans-serif;
      font-size: 10pt;">
      <p style="margin: 0px 0px 1.2em ! important;">On 2017-12-08 01:52
        AM, Sven Panne wrote:</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;">… making something
          a CAF is not always an optimization: If your evaluated CAF
          uses e.g. hundreds of MB it might be preferable to <em>not</em>
          have it as a CAF, but to to recompute it instead.</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em ! important;">Good point. However,
        I think it would be very hard for the compiler to detect which
        CAFs use a lot of memory and aren’t referred to very often.</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;">If I haven’t
          missed something recently, CAFs can’t be garbage collected,
          but I would be happy to be corrected here. :-)</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em ! important;">There’s a helpful
        discussion on the Haskell Wiki <a
          href="https://wiki.haskell.org/Constant_applicative_form">here</a>.
        In particular, it says:</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;">A CAF … may only
          be accessible from within the code of one or more functions.
          In order for the garbage collector to be able to reclaim such
          structures, we associate with each function a list of the CAFs
          to which it refers. When garbage collecting a reference to the
          function we collect the CAFs on its list.</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em ! important;">In my case, since
        the function itself is top-level, I assume the CAF can’t be
        garbage-collected.</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;">
        <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;">Enabling
            profiling shouldn’t change the meaning of a program.</p>
        </blockquote>
        <p style="margin: 0px 0px 1.2em ! important;">It doesn’t change
          the meaning, that would really be a desaster, it just changes
          the performance characteristics. This is still not nice, but
          not much different from using different levels of
          optimization: Doing or not doing e.g. strictness analysis
          might change the space complexity etc.</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em ! important;">Yes, I see you’re
        right. However, I guess I was using ‘meaning’ loosely to mean
        ‘is a CAF’ and I assumed a CAF would always be floated. The
        above-mentioned wiki page says, “A CAF can always be lifted to
        the top level of the program.” However, I realize “can” is not
        the same as “should”.</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;">
        <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;">I remember back
            in the day having to be careful with regexes in Python to
            make sure they were always precompiled outside of loops and
            functions, but one of the nice things about Haskell is that
            one can usually let the compiler take care of this.
            (Nowadays Python gets around this by caching compiled
            regexes, but I prefer Haskell’s statically-optimized
            approach.)</p>
        </blockquote>
        <p style="margin: 0px 0px 1.2em ! important;">I think totally
          relying on the compiler for performance is a common
          misconception, because things are often more tricky than
          initially thought. In our example: Time vs. space tradeoff,
          and there is no universally “right” solution.</p>
      </blockquote>
      <p style="margin: 0px 0px 1.2em ! important;">Good point. Having
        great optimization isn’t a justification for complete mental
        laziness on the part of the programmer! However, I did find the
        behaviour in this case surprising and unintuitive, given ghc’s
        usual ability to optimize things, and having it change on me
        when I enabled profiling left me wondering where to go next. The
        code I presented here is considerably simplified from the
        original program, and represents a lot of work already expended
        trying to get to the root of the problem.</p>
      <div
title="MDH:T24gMjAxNy0xMi0wOCAwMTo1MiBBTSwgU3ZlbiBQYW5uZSB3cm90ZTo8YnI+Jmd0OyDigKYgbWFraW5nIHNvbWV0aGluZyBhIENBRiBpcyBub3QgYWx3YXlzIGFuIG9wdGltaXphdGlvbjogSWYgeW91
ciBldmFsdWF0ZWQgQ0FGIHVzZXMgZS5nLiBodW5kcmVkcyBvZiBNQiBpdCBtaWdodCBiZSBwcmVm
ZXJhYmxlIHRvICpub3QqIGhhdmUgaXQgYXMgYSBDQUYsIGJ1dCB0byB0byByZWNvbXB1dGUgaXQg
aW5zdGVhZC48YnI+PGJyPkdvb2QgcG9pbnQuIEhvd2V2ZXIsIEkgdGhpbmsgaXQgd291bGQgYmUg
dmVyeSBoYXJkIGZvciB0aGUgY29tcGlsZXIgdG8gZGV0ZWN0IHdoaWNoIENBRnMgdXNlIGEgbG90
IG9mIG1lbW9yeSBhbmQgYXJlbid0IHJlZmVycmVkIHRvIHZlcnkgb2Z0ZW4uPGJyPjxicj4mZ3Q7
IElmIEkgaGF2ZW4ndCBtaXNzZWQgc29tZXRoaW5nIHJlY2VudGx5LCBDQUZzIGNhbid0IGJlIGdh
cmJhZ2UgY29sbGVjdGVkLCBidXQgSSB3b3VsZCBiZSBoYXBweSB0byBiZSBjb3JyZWN0ZWQgaGVy
ZS4gOi0pPGJyPjxicj5UaGVyZSdzIGEgaGVscGZ1bCBkaXNjdXNzaW9uIG9uIHRoZSBIYXNrZWxs
IFdpa2kgW2hlcmVdKGh0dHBzOi8vd2lraS5oYXNrZWxsLm9yZy9Db25zdGFudF9hcHBsaWNhdGl2
ZV9mb3JtKS4gSW4gcGFydGljdWxhciwgaXQgc2F5czo8YnI+PGJyPiZndDsgQSBDQUYg4oCmIG1h
eSBvbmx5IGJlIGFjY2Vzc2libGUgZnJvbSB3aXRoaW4gdGhlIGNvZGUgb2Ygb25lIG9yIG1vcmUg
ZnVuY3Rpb25zLiBJbiBvcmRlciBmb3IgdGhlIGdhcmJhZ2UgY29sbGVjdG9yIHRvIGJlIGFibGUg
dG8gcmVjbGFpbSBzdWNoIHN0cnVjdHVyZXMsIHdlIGFzc29jaWF0ZSB3aXRoIGVhY2ggZnVuY3Rp
b24gYSBsaXN0IG9mIHRoZSBDQUZzIHRvIHdoaWNoIGl0IHJlZmVycy4gV2hlbiBnYXJiYWdlIGNv
bGxlY3RpbmcgYSByZWZlcmVuY2UgdG8gdGhlIGZ1bmN0aW9uIHdlIGNvbGxlY3QgdGhlIENBRnMg
b24gaXRzIGxpc3QuPGJyPjxicj5JbiBteSBjYXNlLCBzaW5jZSB0aGUgZnVuY3Rpb24gaXRzZWxm
IGlzIHRvcC1sZXZlbCwgSSBhc3N1bWUgdGhlIENBRiBjYW4ndCBiZSBnYXJiYWdlLWNvbGxlY3Rl
ZC48YnI+PGJyPiZndDsmZ3Q7IEVuYWJsaW5nIHByb2ZpbGluZyBzaG91bGRu4oCZdCBjaGFuZ2Ug
dGhlIG1lYW5pbmcgb2YgYSBwcm9ncmFtLjxicj4mZ3Q7PGJyPiZndDsgSXQgZG9lc24ndCBjaGFu
Z2UgdGhlIG1lYW5pbmcsIHRoYXQgd291bGQgcmVhbGx5IGJlIGEgZGVzYXN0ZXIsIGl0IGp1c3Qg
Y2hhbmdlcyB0aGUgcGVyZm9ybWFuY2UgY2hhcmFjdGVyaXN0aWNzLiBUaGlzIGlzIHN0aWxsIG5v
dCBuaWNlLCBidXQgbm90IG11Y2ggZGlmZmVyZW50IGZyb20gdXNpbmcgZGlmZmVyZW50IGxldmVs
cyBvZiBvcHRpbWl6YXRpb246IERvaW5nIG9yIG5vdCBkb2luZyBlLmcuIHN0cmljdG5lc3MgYW5h
bHlzaXMgbWlnaHQgY2hhbmdlIHRoZSBzcGFjZSBjb21wbGV4aXR5IGV0Yy48YnI+PGJyPlllcywg
SSBzZWUgeW91J3JlIHJpZ2h0LiBIb3dldmVyLCBJIGd1ZXNzIEkgd2FzIHVzaW5nICdtZWFuaW5n
JyBsb29zZWx5IHRvIG1lYW4gJ2lzIGEgQ0FGJyBhbmQgSSBhc3N1bWVkIGEgQ0FGIHdvdWxkIGFs
d2F5cyBiZSBmbG9hdGVkLiBUaGUgYWJvdmUtbWVudGlvbmVkIHdpa2kgcGFnZSBzYXlzLCAiQSBD
QUYgY2FuIGFsd2F5cyBiZSBsaWZ0ZWQgdG8gdGhlIHRvcCBsZXZlbCBvZiB0aGUgcHJvZ3JhbS4i
IEhvd2V2ZXIsIEkgcmVhbGl6ZSAiY2FuIiBpcyBub3QgdGhlIHNhbWUgYXMgInNob3VsZCIuPGJy
Pjxicj4mZ3Q7Jmd0OyBJIHJlbWVtYmVyIGJhY2sgaW4gdGhlIGRheSBoYXZpbmcgdG8gYmUgY2Fy
ZWZ1bCB3aXRoIHJlZ2V4ZXMgaW4gUHl0aG9uIHRvIG1ha2Ugc3VyZSB0aGV5IHdlcmUgYWx3YXlz
IHByZWNvbXBpbGVkIG91dHNpZGUgb2YgbG9vcHMgYW5kIGZ1bmN0aW9ucywgYnV0IG9uZSBvZiB0
aGUgbmljZSB0aGluZ3MgYWJvdXQgSGFza2VsbCBpcyB0aGF0IG9uZSBjYW4gdXN1YWxseSBsZXQg
dGhlIGNvbXBpbGVyIHRha2UgY2FyZSBvZiB0aGlzLiAoTm93YWRheXMgUHl0aG9uIGdldHMgYXJv
dW5kIHRoaXMgYnkgY2FjaGluZyBjb21waWxlZCByZWdleGVzLCBidXQgSSBwcmVmZXIgSGFza2Vs
bOKAmXMgc3RhdGljYWxseS1vcHRpbWl6ZWQgYXBwcm9hY2guKTxicj4mZ3Q7PGJyPiZndDsgSSB0
aGluayB0b3RhbGx5IHJlbHlpbmcgb24gdGhlIGNvbXBpbGVyIGZvciBwZXJmb3JtYW5jZSBpcyBh
IGNvbW1vbiBtaXNjb25jZXB0aW9uLCBiZWNhdXNlIHRoaW5ncyBhcmUgb2Z0ZW4gbW9yZSB0cmlj
a3kgdGhhbiBpbml0aWFsbHkgdGhvdWdodC4gSW4gb3VyIGV4YW1wbGU6IFRpbWUgdnMuIHNwYWNl
IHRyYWRlb2ZmLCBhbmQgdGhlcmUgaXMgbm8gdW5pdmVyc2FsbHkgInJpZ2h0IiBzb2x1dGlvbi48
YnI+PGJyPkdvb2QgcG9pbnQuIEhhdmluZyBncmVhdCBvcHRpbWl6YXRpb24gaXNuJ3QgYSBqdXN0
aWZpY2F0aW9uIGZvciBjb21wbGV0ZSBtZW50YWwgbGF6aW5lc3Mgb24gdGhlIHBhcnQgb2YgdGhl
IHByb2dyYW1tZXIhIEhvd2V2ZXIsIEkgZGlkIGZpbmQgdGhlIGJlaGF2aW91ciBpbiB0aGlzIGNh
c2Ugc3VycHJpc2luZyBhbmQgdW5pbnR1aXRpdmUsIGdpdmVuIGdoYydzIHVzdWFsIGFiaWxpdHkg
dG8gb3B0aW1pemUgdGhpbmdzLCBhbmQgaGF2aW5nIGl0IGNoYW5nZSBvbiBtZSB3aGVuIEkgZW5h
YmxlZCBwcm9maWxpbmcgbGVmdCBtZSB3b25kZXJpbmcgd2hlcmUgdG8gZ28gbmV4dC4gVGhlIGNv
ZGUgSSBwcmVzZW50ZWQgaGVyZSBpcyBjb25zaWRlcmFibHkgc2ltcGxpZmllZCBmcm9tIHRoZSBv
cmlnaW5hbCBwcm9ncmFtLCBhbmQgcmVwcmVzZW50cyBhIGxvdCBvZiB3b3JrIGFscmVhZHkgZXhw
ZW5kZWQgdHJ5aW5nIHRvIGdldCB0byB0aGUgcm9vdCBvZiB0aGUgcHJvYmxlbS48YnI+"
style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;">​</div>
    </div>
  </body>
</html>