增加Observable.Create for F#

时间:2012-12-03 21:06:50

标签: f# system.reactive

我想补充一下

public static IObservable<TSource> Create<TSource>(
    Func<IObserver<TSource>, Action> subscribe)
{...}

在F#中使用,以便不是使用函数或动作调用,而是使用标准F#类型,即IObserver -> (unit -> unit)

我该如何做到这一点?

编辑:

添加完整示例。不确定为什么obsAction不起作用。

open System
open System.Reactive
open System.Reactive.Disposables
open System.Reactive.Linq


type Observable with
  static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

let obsDispose (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args ->     observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    Disposable.Empty

let obsAction (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    let action() =
        timer.Elapsed.RemoveHandler(handlerTick)
        timer.Elapsed.RemoveHandler(handlerElapse)
        timer.Dispose()
    action

let obsOtherAction (observer:IObserver<_>) =
    let timer = new System.Timers.Timer()
    timer.Interval <- 1000.00
    let handlerTick = new Timers.ElapsedEventHandler(fun sender args -> observer.OnNext("tick"))
    let handlerElapse = new Timers.ElapsedEventHandler(fun sender args -> printfn "%A" args.SignalTime)
    timer.Elapsed.AddHandler(handlerTick)
    timer.Elapsed.AddHandler(handlerElapse)
    timer.Start()
    new System.Action( fun () ->
        timer.Elapsed.RemoveHandler(handlerTick)
        timer.Elapsed.RemoveHandler(handlerElapse)
        timer.Dispose())

let worksNeverStops = obsDispose |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let actionWorks = obsOtherAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)
let doesNotWork = obsAction |> Observable.Create |> Observable.subscribe(fun time -> printfn "Time: %A" time)

1 个答案:

答案 0 :(得分:2)

你遇到的问题是FP问题。

在,

  static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

subscribe的类型为IObserver<_> -> unit -> unit

现在IObserver<_> -> unit -> unit之间存在细微差别 和IObserver<_> -> Action其中Action : unit -> unit。区别在于前者是咖喱,而后者不是。

当观察者订阅时,subscribe observer会返回一个方法,()可以应用于unit - 您的订阅方法将永远不会被调用,直到最后()应用 - 直到它取消订阅才会被分离。

你可以通过强迫它不被咖喱来克服它:

let action() = ... | let action = (subscribe observer)
Action(action)

此外:

如果检查IL,则为Invoke生成的FastFunc的等效VB(函数引用在VB中更清晰)版本

 static member Create(subscribe) = 
    Observable.Create(fun observer -> Action(subscribe observer))

是:

Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
    Return New Action(AddressOf New Observable-Create-Static@27-1(Of a)(Me.subscribe, arg).Invoke)
End Function

和for:

  static member Create(subscribe) = 
    Observable.Create(fun observer ->
      let action = subscribe observer
      Action(action))

是:

Friend Function Invoke(ByVal arg As IObserver(Of a)) As Action
    Return New Action(AddressOf New Observable-Create-Static@28-1(Me.subscribe.Invoke(arg)).Invoke)
End Function
  1. AddressOf New Closure(Me.subscribe, arg).Invoke - &gt;在调用dispose操作之前,订阅函数不会被调用。

  2. AddressOf New Closure(Me.subscribe.Invoke(arg)).Invoke - &gt;实际调用了subscribe函数,并按预期返回结果操作。

  3. 我希望现在很清楚为什么第二种情况有效,而不是第一种情况。