         }
     }
 
-    /// Emit a pair of latest elements from each signal. Starts when both signals emit at least one element,
-    /// and emits `.next` when either signal generates an element.
+    /// Emit a pair of the latest elements from each signal. Starts when both signals emit at least one element.
+    /// Emits a pair element when any of the two signals emit an element.
+    ///
+    /// Check out interactive example: [https://rxmarbles.com/#combineLatest](https://rxmarbles.com/#combineLatest)
     public func combineLatest<O: SignalProtocol>(with other: O) -> Signal<(Element, O.Element), Error> where O.Error == Error {
         return combineLatest(with: other, combine: { ($0, $1) })
     }
 
-    /// First emit events from source and then from `other` signal.
-    public func concat(with other: Signal<Element, Error>) -> Signal<Element, Error> {
+    /// First propagate all elements from the source signal and then all elements from the `other` signal.
+    ///
+    /// Check out interactive example: [https://rxmarbles.com/#concat](https://rxmarbles.com/#concat)
+    public func concat<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
         return Signal { observer in
             let serialDisposable = SerialDisposable(otherDisposable: nil)
             serialDisposable.otherDisposable = self.observe { event in

        }
    }

    /// Merge emissions from both the receiver and the other signal into one signal.
    public func merge<O: SignalProtocol>(with other: O) -> Signal<Element, Error> where O.Element == Element, O.Error == Error {
        return Signal(sequence: [self.toSignal(), other.toSignal()]).merge()
    }

        return combineLatest(with: other.scan((), { _, _ in }).castError()) { my, _ in my }
    }

    /// Combine the receiver and the `other` signal into a signal whose elements are combinations of the
    /// receiver elements with the latest elements from the `other` signal.
    ///
    /// Check out interactive example: [https://rxmarbles.com/#withLatestFrom](https://rxmarbles.com/#withLatestFrom)
    public func with<O: SignalProtocol, U>(latestFrom other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
        return Signal { observer in
            var latest: O.Element? = nil
            let compositeDisposable = CompositeDisposable()
            compositeDisposable += other.observe { event in
                switch event {
                case .next(let element):
                    latest = element
                case .failed(let error):
                    observer.failed(error)
                case .completed:
                    break
                }
            }
            compositeDisposable += self.observe { event in
                switch event {
                case .completed:
                    observer.completed()
                case .failed(let error):
                    observer.failed(error)
                case .next(let element):
                    if let latest = latest {
                        observer.next(combine(element, latest))
                    }
                }
            }
            return compositeDisposable
        }
    }

    /// Combine the receiver and the `other` signal into a signal whose elements are combinations of the
    /// receiver elements with the latest elements from the `other` signal.
    ///
    /// Check out interactive example: [https://rxmarbles.com/#withLatestFrom](https://rxmarbles.com/#withLatestFrom)
    public func with<O: SignalProtocol>(latestFrom other: O) -> Signal<(Element, O.Element), Error> where O.Error == Error {
        return with(latestFrom: other, combine: { ($0, $1) })
    }

    /// Zip elements from the receiver and the `other` signal.
    /// Zip differs from `combineLatest` in that the combinations are produced from elements at same positions.
    ///
    /// Check out interactive example: [https://rxmarbles.com/#zip](https://rxmarbles.com/#zip)
    public func zip<O: SignalProtocol, U>(with other: O, combine: @escaping (Element, O.Element) -> U) -> Signal<U, Error> where O.Error == Error {
        return Signal { observer in
            let lock = NSRecursiveLock(name: "reactive_kit.zip")
