title: Sharing of partially applied functions
body: <p>I am currently experimenting with sharing of partially applied functions. In order to make sharing visible, I use the tracing effect. In order to illustrate my problem, I first show a <a href="https://gist.github.com/nbun/a601ed0a964ab08649775e83db4f88cf" rel="nofollow noreferrer">simplified example</a>.</p>
  
  <pre class="lang-hs prettyprint-override"><code>f1, f2, f3, f4 :: Int -&gt; Int
  f1   = \x -&gt; trace "f1" 0 + x
  f2 x = trace "f2" 0 + x
  f3   = (trace "f3" 0 +)
  f4   = (+) (trace "f4" 0)
  </code></pre>
  
  <p>I compare these functions in the following scenario, where <code>f1</code> is substituted by the different functions.</p>
  
  <pre class="lang-hs prettyprint-override"><code>apply :: (Int -&gt; Int) -&gt; (Int -&gt; Int) -&gt; Int
  apply f g = f 42 + g 42
  
  result = let f = f1
           in apply f f
  </code></pre>
  
  <p>The output (compiled without optimizations) is as follows.</p>
  
  <pre><code>f1 f1 f2 f2 f3 f4 336
  </code></pre>
  
  <p>The core code shows that both <code>f1</code> and <code>f2</code> are lambda functions, while <code>f3</code> and <code>f4</code> are partially applied functions. In the first case, there appears to be no sharing of the argument within the body of the lambda, while it works in the second case. Enabling compiler optimizations leads to sharing for all defintions, but I am interested in why there is no sharing within lambda functions.</p>