How do I turn an IObservable<IObservable<T>> into an IObservable<T>?

Viewed 100

Let say I have a function which returns IObservable<T> and this function needs initial state.

let myObservable (initialState: T) :IObservable<T> = (...)

but I can get initial state only from another observable which emits only once

let initializeObservable: IObservable<S> = (...)

how can I combine these two to get IObservable<T>?

let resultObservable = initializeObservable |>
                       Observable.map (fun initialState -> myObservable initialState)

Currently resultObservable is IObservable<IObservable<T>> but I would like it to be IObservable<T> and emit values from myObservable after initial state is ready.

2 Answers

In general if you take an elevated type A<T>, lower it to T, project it from T -> U and lift it to get A<U>, that operation is called bind.

Observable.bind (fun init -> myObservable init) initializeObservable

Or to simplify:

initializeObservable |> Observable.bind myObservable

As for your approach, you're pretty much there.

initializeObservable 
|> Observable.map (fun initialState -> myObservable initialState)
|> Observable.mergeInner

Even if your initializeObservable emits n times, you can just merge all the observables together, which is equally valid even if it emits just once.

You can use the F# Reactive extensions:

open FSharp.Control.Reactive.Builders
   
 let result  = 
        observe {
            let! s0 = initializeObservable
            yield! myObservable s0
        }
Related