{"id":878,"date":"2009-10-20T16:50:13","date_gmt":"2009-10-20T14:50:13","guid":{"rendered":"http:\/\/www.navision-blog.de\/2009\/10\/20\/iobservableiobserver-using-the-reactive-framework-with-f\/"},"modified":"2009-10-22T09:56:45","modified_gmt":"2009-10-22T07:56:45","slug":"iobservableiobserver-using-the-reactive-framework-with-f","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2009\/10\/20\/iobservableiobserver-using-the-reactive-framework-with-f\/","title":{"rendered":"IObservable\/IObserver &ndash; Using the Reactive Framework with F#"},"content":{"rendered":"<p>One of the nice new features in .NET 4.0 beta 2 is the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd990377%28VS.100%29.aspx\">IObservable&lt;T&gt;<\/a>\/IObserver&lt;T&gt; support from the Reactive Framework (\u201cRx Framework\u201d or sometimes \u201cLinqToEvents\u201d). It is a really powerful way to use reactive programming in .NET and especially in F# developed by Erik Meijer and his team. <\/p>\n<p>If you want to see some of the beautiful math behind the Reactive Framework you should definitely watch <a href=\"http:\/\/channel9.msdn.com\/shows\/Going+Deep\/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-1-of-2\/\">this<\/a> Expert to Expert video on Channel 9. You can see Brian Beckman and Erik Meijer showing that IObservable&lt;T&gt; is the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Dual_(category_theory)\">mathematical dual<\/a> of IEnumerable&lt;T&gt;.<\/p>\n<h5>What can I do with the Rx Framework?<\/h5>\n<p>Consider this small sample (it is taken from <a href=\"http:\/\/codebetter.com\/blogs\/matthew.podwysocki\/archive\/2009\/10\/19\/f-october-2009-ctp-beta2-f-rx-together-at-last.aspx\">Matthew Podwysocki&#8217;s blog<\/a>): We want to get notified whenever a user clicks on our form and moves the mouse within a special area (XPos and YPos smaller than 100px).<\/p>\n<p>First of all we define our observable by merging and filtering .NET events:<\/p>\n<div style=\"font-family: consolas; background: white; color: black; font-size: 8pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">open<\/span> System.Windows.Forms<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> form = <span style=\"color: blue\">new<\/span> Form(Visible=<span style=\"color: blue\">true<\/span>, TopMost=<span style=\"color: blue\">true<\/span>)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ Creates two observables<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160; &#8211; left is triggered when the left mouse button is down <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; and the mouse is in the area (x &lt; 100 &amp;&amp; y &lt; 100)<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160; &#8211; right is triggered when the right mouse button is down <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; and the mouse is in the area (x &lt; 100 &amp;&amp; y &lt; 100)<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> left,right = <\/p>\n<p style=\"margin: 0px\">&#160; form.MouseDown<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.merge form.MouseMove<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.filter (<span style=\"color: blue\">fun<\/span> args <span style=\"color: blue\">-&gt;<\/span>&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; args.Button = MouseButtons.Left ||<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; args.Button = MouseButtons.Right)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.map (<span style=\"color: blue\">fun<\/span> args <span style=\"color: blue\">-&gt;<\/span> args.X, args.Y, args.Button)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.filter (<span style=\"color: blue\">fun<\/span> (x,y,b) <span style=\"color: blue\">-&gt;<\/span> x &lt; 100 &amp;&amp; y &lt; 100)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.partition (<span style=\"color: blue\">fun<\/span> (_,_,button) <span style=\"color: blue\">-&gt;<\/span> button = MouseButtons.Left)<\/p>\n<\/p><\/div>\n<p>Now it\u2019s easy to subscribe a function to this observable:<\/p>\n<div style=\"font-family: consolas; background: white; color: black; font-size: 8pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> leftSubscription =<\/p>\n<p style=\"margin: 0px\">&#160; left<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.subscribe<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (<span style=\"color: blue\">fun<\/span> (x,y,_) <span style=\"color: blue\">-&gt;<\/span> printfn <span style=\"color: maroon\">&quot;Left (%d,%d)&quot;<\/span> x y)<\/p>\n<\/p><\/div>\n<p>If we want to unsubscribe we only have to dispose the object:<\/p>\n<div style=\"font-family: consolas; background: white; color: black; font-size: 8pt\">\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ unsubscribe<\/span><\/p>\n<p style=\"margin: 0px\">leftSubscription.Dispose()<\/p>\n<\/p><\/div>\n<p>We couldn\u2019t unsubscribe this way with \u201cclassic\u201d .NET events. Remember the \u2013= operator in C# doesn\u2019t work with lambda expressions.<\/p>\n<h5>Exception handling<\/h5>\n<p>We have seen an easy way to subscribe and unsubscribe to complicated observables but what should we do if an error occurs? As far as I know this case is not implemented for F# at the moment, but we can easily add this functionality:<\/p>\n<div style=\"font-family: consolas; background: white; color: black; font-size: 8pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">module<\/span> Observable<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ Creates an observer with the given functions<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> createObserver next error completed =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<span style=\"color: blue\">new<\/span> System.IObserver&lt;_&gt; <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">member<\/span> this.OnCompleted() = completed()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">member<\/span> this.OnError(e) = error e<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">member<\/span> this.OnNext(args) = next args}<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ Subscribes an observer with the given functions <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160;&#160; param1: OnNext&#160;&#160;&#160;&#160;&#160;&#160;&#160; (T -&gt; unit)<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160;&#160; param2: OnError&#160;&#160;&#160;&#160;&#160;&#160; (Exception -&gt; unit)<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160;&#160; param3: OnCompleted&#160;&#160; (unit -&gt; unit)<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/&#160;&#160; param4: observable<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> subscribeComplete next error completed (observable:System.IObservable&lt;_&gt;) =<\/p>\n<p style=\"margin: 0px\">&#160; createObserver next error completed<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; observable.Subscribe<\/p>\n<\/p><\/div>\n<p>Now we are able to create a complete IObserver&lt;T&gt; object<t> and register the 3 functions:<\/p>\n<div style=\"font-family: consolas; background: white; color: black; font-size: 8pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> rightSubscription =<\/p>\n<p style=\"margin: 0px\">&#160; right<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.subscribeComplete<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (<span style=\"color: blue\">fun<\/span> (x,y,_) <span style=\"color: blue\">-&gt;<\/span> printfn <span style=\"color: maroon\">&quot;Right (%d,%d)&quot;<\/span> x y)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (<span style=\"color: blue\">fun<\/span> error&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> printfn <span style=\"color: maroon\">&quot;Error: %s&quot;<\/span> error.Message)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (<span style=\"color: blue\">fun<\/span> ()&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">-&gt;<\/span> printfn <span style=\"color: maroon\">&quot;Ready.&quot;<\/span>)<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>One of the nice new features in .NET 4.0 beta 2 is the IObservable&lt;T&gt;\/IObserver&lt;T&gt; support from the Reactive Framework (\u201cRx Framework\u201d or sometimes \u201cLinqToEvents\u201d). It is a really powerful way to use reactive programming in .NET and especially in F# developed by Erik Meijer and his team. If you want to see some of the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[448],"tags":[664,579,578],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/878"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=878"}],"version-history":[{"count":3,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/878\/revisions"}],"predecessor-version":[{"id":881,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/878\/revisions\/881"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=878"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=878"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=878"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}