title: Fold that's both constant-space and short-circuiting
body: <p>I'm trying to build a Haskell function that does basically the same thing as Prelude's <code>product</code>. Unlike that function, however, it should have these two properties:</p>
  
  <ol>
  <li>It should operate in constant space (ignoring the fact that some numeric types like <code>Integer</code> aren't). For example, I want <code>myProduct (replicate 100000000 1)</code> to eventually return 1, unlike Prelude's <code>product</code> which uses up all of my RAM and then gives <code>*** Exception: stack overflow</code>.</li>
  <li>It should short-circuit when it encounters a 0. For example, I want <code>myProduct (0:undefined)</code> to return 0, unlike Prelude's <code>product</code> which gives <code>*** Exception: Prelude.undefined</code>.</li>
  </ol>
  
  <p>Here's what I've come up with so far:</p>
  
  <pre><code>myProduct :: (Eq n, Num n) =&gt; [n] -&gt; n
  myProduct = go 1
    where go acc (x:xs) = if x == 0 then 0 else acc `seq` go (acc * x) xs
          go acc []     = acc
  </code></pre>
  
  <p>That works exactly how I want it to for lists, but I'd like to generalize it to have type <code>(Foldable t, Eq n, Num n) =&gt; t n -&gt; n</code>. Is it possible to do this with any of the folds? If I just use <code>foldr</code>, then it will short-circuit but won't be constant-space, and if I just use <code>foldl'</code>, then it will be constant-space but won't short-circuit.</p>