fsprojects / FSharp.Control.Reactive

Extensions and wrappers for using Reactive Extensions (Rx) with F#.
http://fsprojects.github.io/FSharp.Control.Reactive
Other
284 stars 60 forks source link

Should Observable.fromEventHandler<'EventArgs> return IObservable<'EventArgs> instead of IObservable<object>? #129

Closed danien closed 4 years ago

danien commented 4 years ago

Description

I'm trying to use Observable.fromEventHandler<SomeEventArgs> to create an observable out of an existing EventHandler as below:

    public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurface;

    let _paintCanvasObservable =
        Observable.fromEventHandler<SKPaintGLSurfaceEventArgs>
            (fun handler -> this.canvasView.PaintSurface.AddHandler(handler))
            (fun handler -> this.canvasView.PaintSurface.RemoveHandler(handler))

But the signature for the function appears to be hardcoded to return an IObservable<object>:

public static IObservable<object> fromEventHandler<EventArgs>(FSharpFunc<EventHandler<object>, Unit> addHandler, FSharpFunc<EventHandler<object>, Unit> removeHandler) where EventArgs : EventArgs

so I get a type mismatch error:

Error FS0001: Type mismatch. Expecting a 'EventHandler<SKPaintGLSurfaceEventArgs>' but given a 'EventHandler<obj>' The type 'SKPaintGLSurfaceEventArgs' does not match the type 'obj' (FS0001)

Repro steps

See example code above.

Expected behavior

Is Observable.fromEventHandler<'EventArgs> intended to return an IObservable<'EventArgs> instead of IObservable<object>? Or am I understanding and using this function incorrectly?

Actual behavior

Observable.fromEventHandler<'EventArgs> returns IObservable<object>, resulting in a type-mismatch error as mentioned above.

Known workarounds

If I modify the fromEventHandler code at https://github.com/fsprojects/FSharp.Control.Reactive/blob/master/src/FSharp.Control.Reactive/Observable.fs#L785 to explicitly specify the 'EventArgs type in the addHandler and removeHandler type parameters,

    let fromEventHandler<'EventArgs when 'EventArgs:> EventArgs>
        //( addHandler    : EventHandler<_> -> unit )
        //( removeHandler : EventHandler<_> -> unit )  =
        ( addHandler    : EventHandler<'EventArgs> -> unit )
        ( removeHandler : EventHandler<'EventArgs> -> unit )  =
        {
            // no other changes.   
        }

the function signature becomes

public static IObservable<EventArgs> fromEventHandler<EventArgs>(FSharpFunc<EventHandler<EventArgs>, Unit> addHandler, FSharpFunc<EventHandler<EventArgs>, Unit> removeHandler) where EventArgs : EventArgs

which is what I need (and expected).

Related information

danien commented 4 years ago

Submitted fix with PR #130.

panesofglass commented 4 years ago

Is this fixed in 4.3.0?

danien commented 4 years ago

Yes, it is. Thank you!