 
 /// `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]) |> concat
-}
-
-/// Maps each event from `producer` to a new producer, then
-/// concatenates the resulting producers together.
-public func concatMap<T, U, E>(transform: T -> SignalProducer<U, E>)(producer: SignalProducer<T, E>) -> SignalProducer<U, E> {
-    return producer |> map(transform) |> concat
+	return SignalProducer(values: [producer, next]) |> join(.Concat)
 }
 
 /// Returns a producer that forwards values from the latest producer sent on

///
/// The returned producer completes when `producer` and the latest inner
/// producer have both completed.
public func latest<T, E>(producer: SignalProducer<SignalProducer<T, E>, E>) -> SignalProducer<T, E> {
	return SignalProducer<T, E> { sink, disposable in
		producer.startWithSignal { outerSignal, outerDisposable in
			disposable.addDisposable(outerDisposable)

///
/// The returned signal completes only when `producer` and all signals
/// emitted from `producer` complete.
private func concat<T, E>(producer: SignalProducer<SignalProducer<T, E>, E>) -> SignalProducer<T, E> {
	return SignalProducer { observer, disposable in
		let state = ConcatState(observer: observer, disposable: disposable)

