 /// `replacement`. Any error sent from `producer` is forwarded immediately, in
 /// which case `replacement` will not be started, and none of its events will be
 /// be forwarded. All values sent from `producer` are ignored.
-public func then<T, U, E>(replacement: SignalProducer<U, E>)(producer: SignalProducer<T, E>) -> SignalProducer<U, E> {
-	let relay = SignalProducer<U, E> { observer, observerDisposable in
-		producer.startWithSignal { signal, signalDisposable in
-			observerDisposable.addDisposable(signalDisposable)
-
-			signal.observe(error: { error in
-				sendError(observer, error)
-			}, completed: {
-				sendCompleted(observer)
-			}, interrupted: {
-				sendInterrupted(observer)
-			})
-		}
-	}
-
-	return relay |> concat(replacement)
+public func then<T, U, E>(replacement: SignalProducer<U, E>) -> SignalProducer<T, E> -> SignalProducer<U, E> {
+	return { producer in
+		let relay = SignalProducer<U, E> { observer, observerDisposable in
+			producer.startWithSignal { signal, signalDisposable in
+				observerDisposable.addDisposable(signalDisposable)
+
+				signal.observe(error: { error in
+					sendError(observer, error)
+				}, completed: {
+					sendCompleted(observer)
+				}, interrupted: {
+					sendInterrupted(observer)
+				})
+			}
+		}
+
+		return relay |> concat(replacement)
+	}
 }
 
 /// Starts the producer, then blocks, waiting for the first value.

}

/// `concat`s `next` onto `producer`.
public func concat<T, E>(next: SignalProducer<T, E>)(producer: SignalProducer<T, E>) -> SignalProducer<T, E> {
	return SignalProducer(values: [producer, next]) |> flatten(.Concat)
}

/// Repeats `producer` a total of `count` times.
/// Repeating `1` times results in a equivalent signal producer.
public func times<T, E>(count: Int)(producer: SignalProducer<T, E>) -> SignalProducer<T, E> {
	precondition(count >= 0)

	if count == 0 {
		return .empty
	} else if count == 1 {
		return producer
	}

	return SignalProducer { observer, disposable in
		let serialDisposable = SerialDisposable()
		disposable.addDisposable(serialDisposable)

		let iterate: Int -> () = fix { recur in
			{ current in
				producer.startWithSignal { signal, signalDisposable in
					serialDisposable.innerDisposable = signalDisposable

					signal.observe(Signal.Observer { event in
						switch event {
						case .Completed:
							let remainingTimes = current - 1
							if remainingTimes > 0 {
								recur(remainingTimes)
							} else {
								sendCompleted(observer)
							}

						default:
							observer.put(event)
						}
					})
				}
			}
		}

		iterate(count)
	}
}

/// Ignores errors up to `count` times.
public func retry<T, E>(count: Int)(producer: SignalProducer<T, E>) -> SignalProducer<T, E> {
	precondition(count >= 0)

	if count == 0 {
		return producer
	} else {
		return producer |> catch { _ in
			producer |> retry(count - 1)
		}
	}
}

///
/// Returns a producer that will send values from `producer`, sampled (possibly
/// multiple times) by `sampler`, then complete once both inputs have completed.
public func sampleOn<T, E>(sampler: SignalProducer<(), NoError>) -> SignalProducer<T, E> -> SignalProducer<T, E> {
	return { producer in
		return producer.lift(sampleOn)(sampler)
	}
}

/// Forwards events from `producer` until `trigger` sends a Next or Completed
/// event, at which point the returned producer will complete.
public func takeUntil<T, E>(trigger: SignalProducer<(), NoError>) -> SignalProducer<T, E> -> SignalProducer<T, E> {
	return { producer in
		return producer.lift(takeUntil)(trigger)
	}
}

/// Forwards events from `producer` until `replacement` begins sending events.
