title: What are good reasons for choosing invariance in an API like Stream.reduce()?
body: <p>Reviewing Java 8 <code>Stream</code> API design, I was surprised by the generic invariance on the <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#reduce-U-java.util.function.BiFunction-java.util.function.BinaryOperator-" rel="noreferrer"><code>Stream.reduce()</code></a> arguments:</p>
  
  <pre><code>&lt;U&gt; U reduce(U identity,
               BiFunction&lt;U,? super T,U&gt; accumulator,
               BinaryOperator&lt;U&gt; combiner)
  </code></pre>
  
  <p>A seemingly more versatile version of the same API might have applied covariance / contravariance on individual references to <code>U</code>, such as:</p>
  
  <pre><code>&lt;U&gt; U reduce(U identity,
               BiFunction&lt;? super U, ? super T, ? extends U&gt; accumulator,
               BiFunction&lt;? super U, ? super U, ? extends U&gt; combiner)
  </code></pre>
  
  <p>This would allow for the following, which isn't possible, currently:</p>
  
  <pre><code>// Assuming we want to reuse these tools all over the place:
  BiFunction&lt;Number, Number, Double&gt; numberAdder =
      (t, u) -&gt; t.doubleValue() + u.doubleValue();
  
  // This currently doesn't work, but would work with the suggestion
  Stream&lt;Number&gt; stream = Stream.of(1, 2L, 3.0);
  double sum = stream.reduce(0.0, numberAdder, numberAdder);
  </code></pre>
  
  <p>Workaround, use method references to "coerce" the types into the target type:</p>
  
  <pre><code>double sum = stream.reduce(0.0, numberAdder::apply, numberAdder::apply);
  </code></pre>
  
  <p>C# doesn't have this particular problem, as <a href="https://msdn.microsoft.com/en-us/library/bb534647(v=vs.110).aspx" rel="noreferrer"><code>Func(T1, T2, TResult)</code></a> is defined as follows, using declaration-site variance, which means that any API using <code>Func</code> gets this behaviour for free:</p>
  
  <pre class="lang-c# prettyprint-override"><code>public delegate TResult Func&lt;in T1, in T2, out TResult&gt;(
      T1 arg1,
      T2 arg2
  )
  </code></pre>
  
  <p>What are the advantages (and possibly, the reasons for EG decisions) of the existing design over the suggested design?</p>
  
  <p>Or, asked differently, what are the caveats of the suggested design that I might be overlooking (e.g. type inference difficulties, parallelisation constraints, or constraints specific to the reduction operation such as e.g. associativity, anticipation of a future Java's declaration-site variance on <code>BiFunction&lt;in T, in U, out R&gt;</code>, ...)?</p>