Prevent SOE on Stream traverse with Future

As title says.
OK, more benchmarks!

    @State(Scope.Benchmark)
    class ApState {
      val fa = Future(1)
      val fab = Future({ (n: Int) => n + 1 })
      Await.result(fa, 1.seconds)
      Await.result(fab, 1.seconds)
    }
    
    class ApBenchmark {
    
      @GenerateMicroBenchmark
      def apFuture0(s: ApState) = {
        val result = s.fab zip s.fa map { case (f, a) => f(a) }
        Await.result(result, 5.seconds)
      }
    
      @GenerateMicroBenchmark
      def apFuture1(s: ApState) = {
        val fa0 = Future(s.fa).flatMap(a => a)
        val result = s.fab zip fa0 map { case (f, a) => f(a) }
        Await.result(result, 5.seconds)
      }
    
      @GenerateMicroBenchmark
      def apFuture2(s: ApState) = {
        val ffa = Future(s.fa)
        val result = ffa.flatMap { fa0 => s.fab zip fa0 map { case (f, a) => f(a) } }
        Await.result(result, 5.seconds)
      }
    }

We are ignoring the cost of `fab`/`fa`, since we're stuck with them in all cases, but they do add a little as well.

 * `apFuture0` is what the original parallel `ap` was
 * `apFuture1` is the new one that uses `join`
 * `apFuture2` is yet another one that remains parallel, but tries to save 1 thunk

And the result:

    Benchmark                                Mode   Samples         Mean   Mean error    Units
    n.t.s.b.e.HelloBenchmark.apFuture0      thrpt        20       92.326        1.561   ops/ms
    n.t.s.b.e.HelloBenchmark.apFuture1      thrpt        20       72.791        1.661   ops/ms
    n.t.s.b.e.HelloBenchmark.apFuture2      thrpt        20       71.486        1.768   ops/ms

So, basically, we can all agree we are losing some performance. But, the overall price is not that high. Keep in mind, this is purely the cost of `ap` itself, and doesn't include any of the work you were actually doing or any of the overhead of various `traverseImpl`.