 ///
 /// If any of the elements resolves to an error, the resulting `Deferred` will contain that error.
 /// If the reducing function throws an error, the resulting `Deferred` will contain that error.
-/// The combined `Deferred` will use a serial queue at the current qos class.
-///
-/// - parameter deferreds: an array of `Deferred`
+/// The combined `Deferred` will use a new queue at the requested (or current) QoS.
+///
+/// - parameter qos: the QoS at which the `reduce` operation and its notifications should occur; defaults to the current QoS
+/// - parameter deferreds: a `Sequence` of `Deferred`
+/// - parameter initial: a value to use as the initial accumulating value
 /// - parameter combine: a reducing function
 /// - returns: a new `Deferred`
-
-public func reduce<S: Sequence, T, U>(qos: DispatchQoS = DispatchQoS.current ?? .default, _ deferreds: S,
-                                      initial: U, combine: @escaping (U,T) throws -> U) -> Deferred<U>
+/// - 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>(qos: DispatchQoS = DispatchQoS.current ?? .default,
+                                      _ deferreds: S, initial: U,
+                                      combine: @escaping (_ accumulated: U, _ element: T) throws -> U) -> Deferred<U>
   where S.Iterator.Element == Deferred<T>
 {
   let queue = DispatchQueue(label: "reduce-sequence", qos: qos)


// combine two or more Deferred objects into one.

/// Combine an array of `Deferred`s into a new `Deferred` whose value is an array.
/// The combined `Deferred` will become determined after every input `Deferred` is determined.
///
/// If any of the elements resolves to an error, the combined `Deferred` will contain that error.
/// The combined `Deferred` will use the queue from the first element of the input array (unless the input array is empty.)
///
/// - parameter deferreds: an array of `Deferred`
/// - returns: a new `Deferred`

public func combine<Value>(qos: DispatchQoS = DispatchQoS.current ?? .default,
                           _ deferreds: [Deferred<Value>]) -> Deferred<[Value]>
{
  var combined = [Value]()
  combined.reserveCapacity(deferreds.count)

  let reduced = reduce(qos: qos, deferreds, initial: (), combine: { _, value in combined.append(value) })
  return reduced.map { _ in combined }
}

/// Combine a Sequence of `Deferred`s into a new `Deferred` whose value is an array.
/// The combined `Deferred` will become determined after every input `Deferred` has become determined.
///
/// If any of the elements resolves to an error, the combined `Deferred` will contain that error.
/// The combined `Deferred` will use the concurrent queue at the current qos class.
///
/// - parameter deferreds: an array of `Deferred`
/// - returns: a new `Deferred`

public func combine<Value, S: Sequence>(qos: DispatchQoS = DispatchQoS.current ?? .default,

  return firstDetermined(qos: qos, deferreds, cancelOthers: cancelOthers).flatMap { $0 }
}

/// Return the value of the first of an array of `Deferred`s to be determined.
/// Note that if the array is empty the resulting `Deferred` will resolve to a
/// `DeferredError.canceled` error.
/// Note also that if more than one element is already determined at the time
/// the function is called, the earliest one will be considered first.
///
/// - parameter qos: the QoS class at which to execute the new `Deferred`'s notifications
/// - parameter deferreds: a `Sequence` of `Deferred`
/// - parameter cancelOthers: whether to attempt to cancel every `Deferred` that doesn't get determined first (defaults to `false`)
/// - returns: a new `Deferred`

public func firstValue<Value, S: Sequence>(qos: DispatchQoS = DispatchQoS.current ?? .default,
                                           _ deferreds: S, cancelOthers: Bool = false) -> Deferred<Value>
  where S.Iterator.Element: Deferred<Value>
