 		return map(transform).flatten(strategy)
 	}
 }
-
-// These free functions are to workaround compiler crashes when attempting
-// to lift binary signal operators directly with closures.
-
-private func combineLatestWith<T, U, E>(otherSignal: Signal<U, E>) -> Signal<T, E> -> Signal<(T, U), E> {
-	return { $0.combineLatestWith(otherSignal) }
-}
-
-private func zipWith<T, U, E>(otherSignal: Signal<U, E>) -> Signal<T, E> -> Signal<(T, U), E> {
-	return { $0.zipWith(otherSignal) }
-}
-
-private func sampleOn<T, E>(sampler: Signal<(), NoError>) -> Signal<T, E> -> Signal<T, E> {
-	return { $0.sampleOn(sampler) }
-}
-
-private func takeUntil<T, E>(trigger: Signal<(), NoError>) -> Signal<T, E> -> Signal<T, E> {
-	return { $0.takeUntil(trigger) }
-}
-
-private func takeUntilReplacement<T, E>(replacement: Signal<T, E>) -> Signal<T, E> -> Signal<T, E> {
-	return { $0.takeUntilReplacement(replacement) }
-}

	/// already.
	@warn_unused_result(message="Did you forget to call `start` on the producer?")
	public func takeUntilReplacement(replacement: SignalProducer<T, E>) -> SignalProducer<T, E> {
		return lift(ReactiveCocoa.takeUntilReplacement)(replacement)
	}

	/// Waits until `self` completes and then forwards the final `count` values

	/// completed, or interrupt if either input producer is interrupted.
	@warn_unused_result(message="Did you forget to call `start` on the producer?")
	public func sampleOn(sampler: SignalProducer<(), NoError>) -> SignalProducer<T, E> {
		return lift { (sg) -> Signal<T, E> -> Signal<T, E> in { $0.sampleOn(sg) } }(sampler)
	}

	/// Forwards events from `self` until `trigger` sends a Next or Completed
	/// event, at which point the returned producer will complete.
	@warn_unused_result(message="Did you forget to call `start` on the producer?")
	public func takeUntil(trigger: SignalProducer<(), NoError>) -> SignalProducer<T, E> {
		return lift { (sg) -> Signal<T, E> -> Signal<T, E> in { $0.takeUntil(sg) } }(trigger)
	}

	/// Forwards events from `self` with history: values of the returned producer
