title: Why are some Prelude functions defined in terms of a locally defined function?
body: <p>I was taking a look at some prelude functions to teach a workmate about recursion and I found that some are written in rather a <em>weird</em> way. Example:</p>
  
  <pre><code>{-# NOINLINE [1] zipWith #-}
  zipWith :: (a -&gt; b -&gt; c) -&gt; [a] -&gt; [b] -&gt; [c]
  zipWith f = go
    where
      go [] _ = []
      go _ [] = []
      go (x:xs) (y:ys) = f x y : go xs ys
  </code></pre>
  
  <p>Why is it written as a call to <code>go</code> where <code>go</code> is defined right afterwards? IMO a more <em>natural</em> way to define it is: </p>
  
  <pre><code>zipWith :: (a -&gt; b -&gt; c) -&gt; [a] -&gt; [b] -&gt; [c]
  zipWith _ [] _ = []
  zipWith _ _ [] = [] 
  zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
  </code></pre>
  
  <p>I guess it is due to some <em>inline / loop-fusion / lazy / whatever-feature</em> that allow <code>GHC</code> to optimize better, but this is the point in which Haskell becomes quite obscure to me. Can anyone explain (as easier as possible) the reason for such a function definition, if there is any.</p>
  
  <h2>Edits</h2>
  
  <p>Many comments, @AndrewRay's answer and in this <a href="https://stackoverflow.com/questions/26243014/why-does-foldr-use-a-helper-function">question</a>, point in the direction of inlining as the reason for such an auxiliar local function. Nevertheless, <code>zipWith</code> is marked with the pragma <code>NOINLINE [1] zipWith</code>, which, up to <a href="https://downloads.haskell.org/~ghc/7.0.3/docs/html/users_guide/pragmas.html#noinline-pragma" rel="nofollow noreferrer">GHC's user guide: 7.13.5.5. Phase control</a>, means to <strong>not</strong> inline before first phase and maybe inline afterwards (for whatever this means). In the linked question, the PO refers to <code>foldr</code> which is implemented using the same trick but without any PRAGMA. I'd argue that the author is avoiding inlining but my knowledge in this is small.</p>
  
  <h2>Edit 2</h2>
  
  <p>added link to <a href="http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.List.html#zipWith" rel="nofollow noreferrer">source</a> definition of <code>zipWith</code></p>