 /// - parameter accumulated: the accumulated value up to this element of the `Collection`
 /// - parameter element: a new element to be accumulated
 
-public func reduce<C: Collection, T, U>(qos: DispatchQoS,
-                                        deferreds: C, initial: U,
-                                        combine: @escaping (_ accumulated: U, _ element: T) throws -> U) -> Deferred<U>
-  where C.Element == Deferred<T>
+public func reduce<C: Collection, T, F, U>(qos: DispatchQoS,
+                                           deferreds: C, initial: U,
+                                           combine: @escaping (_ accumulated: U, _ element: T) -> U) -> Deferred<U, F>
+  where C.Element == Deferred<T, F>
 {
   let queue = DispatchQueue(label: "reduce-collection", qos: qos)
   return reduce(queue: queue, deferreds: deferreds, initial: initial, combine: combine)

/// - parameter accumulated: the accumulated value up to this element of the `Collection`
/// - parameter element: a new element to be accumulated

public func reduce<S: Sequence, T, U>(queue: DispatchQueue,
                                      deferreds: S, initial: U,
                                      combine: @escaping (_ accumulated: U, _ element: T) throws -> U) -> Deferred<U>
  where S.Element == Deferred<T>
{
  // We execute `Sequence.reduce` asynchronously because
  // nothing prevents S from blocking on `Sequence.next()`
  let reduced = Deferred<Deferred<U>>(queue: queue) {
    deferreds.reduce(Deferred(queue: queue, value: initial)) {
      (accumulator, deferred) in
      accumulator.flatMap {
        u in deferred.map(queue: queue) { t in try combine(u,t) }
      }
    }
  }

  return reduced.flatten()

/// - parameter accumulated: the accumulated value up to this element of the `Collection`
/// - parameter element: a new element to be accumulated

public func reduce<S: Sequence, T, F, U>(qos: DispatchQoS,
                                         deferreds: S, initial: U,
                                         combine: @escaping (_ accumulated: U, _ element: T) -> U) -> Deferred<U, F>
  where S.Element == Deferred<T, F>
{
  let queue = DispatchQueue(label: "reduce-sequence", qos: qos)
  return reduce(queue: queue, deferreds: deferreds, initial: initial, combine: combine)
