Reputation: 476
I was hoping to hook cs-sdl up to Rx. I've gotten it to work in C#, but in F# something rather strange starts to happen. I'd like to stick to F# so that I can save on some programming time and pass SDL events as arguments to neatly wrap them in IObservables. Here is how I attempted to do so:
let fromEvent (e: IEvent<'H,'T>) = Observable.FromEventPattern<'H,'T>((fun h -> e.AddHandler(h)),(fun h -> e.RemoveHandler(h)))
All well and good so far. Now to pass it one of the SDL events and get an IObservable...
let MouseMotion = fromEvent(Events.MouseMotion)
And so on and so on goes this set of modules. All the inferred types are correct. MouseMotion is of type IObservable<MouseMotionEventArgs>
Now here is where I actually use this library in another project I made for testing it:
let observer : IObserver<MouseMotionEventArgs> = Observer.Create(Action<MouseMotionEventArgs>(fun x -> System.Console.WriteLine(x.X.ToString())))
ignore <| SdlDotNet.Reactive.CoreInput.MouseMotion.Subscribe(Observer.AsObserver(observer))
Here is what happens when I run it:
System.ArgumentException was unhandled
Message="Type must derive from Delegate.\r\nParameter name: type"
Source="mscorlib"
ParamName="type"
StackTrace:
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
at System.Reactive.Linq.Observable.<>c__DisplayClass19d`2.<FromEvent>b__19b(IObserver`1 observer)
at System.Reactive.AnonymousObservable`1.<>c__DisplayClass1.<Subscribe>b__0()
at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action action)
at System.Reactive.Concurrency.ScheduledItem`2.InvokeCore()
at System.Reactive.Concurrency.ScheduledItem`1.Invoke()
at System.Reactive.Concurrency.CurrentThreadScheduler.Trampoline.Run()
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, TimeSpan dueTime, Func`3 action)
at System.Reactive.Concurrency.CurrentThreadScheduler.Schedule[TState](TState state, Func`3 action)
at System.Reactive.Concurrency.Scheduler.Schedule(IScheduler scheduler, Action action)
at System.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
at <StartupCode$SdlDemo>.$Tutorial.main@() in C:\Users\Barend Venter\Documents\Visual Studio 2008\Projects\SdlDemo\SdlDemo\Tutorial.fs:line 77
InnerException:
I am completely stumped. Why is this happening? Is there some eta-expansion I need to do somewhere?
Upvotes: 0
Views: 415
Reputation: 28765
This may not solve the rest of your problem, but did you notice that IEvent inherits from IObservable? Your fromEvent
function could be implemented as a simple cast...
let fromEvent (e: IEvent<'H,'T>) = e :> IObservable<'T>
Upvotes: 1
Reputation: 11525
Instead of creating your own wrapper functions to adapt F# to Rx, why not just use the functions in the standard F# Control.Observable
module?
Upvotes: 1
Reputation: 476
After some fiddling, I was able to turn the runtime exception into a handy type error. It seems that changing the type of observer from IObserver<MouseMotionEventArgs>
to IObserver<EventPattern<MouseMotionEventArgs>>
does the trick here:
let observer = Observer.Create(fun (x : EventPattern<MouseMotionEventArgs>) -> System.Console.WriteLine(x.EventArgs.X.ToString()))
ignore <| SdlDotNet.Reactive.CoreInput.MouseMotion.Subscribe((observer))
It is perhaps unfortunate that a solution that eluded me for days would come to me so soon after posting here. Hopefully it'll prove useful for someone.
Upvotes: 1