{"id":882,"date":"2009-10-22T17:23:52","date_gmt":"2009-10-22T15:23:52","guid":{"rendered":"http:\/\/www.navision-blog.de\/2009\/10\/22\/iobservableiobserver-using-the-reactive-framework-with-f-part-ii\/"},"modified":"2009-10-22T17:32:06","modified_gmt":"2009-10-22T15:32:06","slug":"iobservable-iobserver-using-the-reactive-framework-with-fsharp-part-ii","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2009\/10\/22\/iobservable-iobserver-using-the-reactive-framework-with-fsharp-part-ii\/","title":{"rendered":"IObservable\/IObserver &ndash; Using the Reactive Framework with F# &#8211; part II"},"content":{"rendered":"<p>In the <a href=\"http:\/\/www.navision-blog.de\/2009\/10\/20\/iobservableiobserver-using-the-reactive-framework-with-f\/\">last article<\/a> I showed how to filter and combine events via the Reactive Framework and how to deal with errors. This time we will create our own observables. <\/p>\n<p>I got the idea for this sample from a very good Expert to Expert video (\u201c<a href=\"http:\/\/channel9.msdn.com\/shows\/Going+Deep\/E2E-Erik-Meijer-and-Wes-Dyer-Reactive-Framework-Rx-Under-the-Hood-1-of-2\/\">Reactive Framework (Rx) Under the Hood<\/a>\u201d) with Erik Meijer and Wes Dyer.<\/p>\n<p>We want to implement an asynchronous dictionary lookup. Whenever sometimes types something into the Textbox, our application starts looking into a dictionary and searches for words starting with the given prefix. <\/p>\n<p><img loading=\"lazy\" style=\"border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px\" title=\"Async Dict\" border=\"0\" alt=\"Async Dict\" src=\"http:\/\/www.navision-blog.de\/images\/IObservableIObserverUsingtheReactiveFram_F306\/image.png\" width=\"240\" height=\"240\" \/><\/p>\n<p>Let&#8217;s start with generating this simple form:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\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>, Text=<span style=\"color: maroon\">&quot;Async dict&quot;<\/span>, <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; TopMost=<span style=\"color: blue\">true<\/span>) <\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> textBox1 = <\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">new<\/span> TextBox(<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Location = <span style=\"color: blue\">new<\/span> System.Drawing.Point(12, 12),<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Size = <span style=\"color: blue\">new<\/span> System.Drawing.Size(260, 20))<\/p>\n<p style=\"margin: 0px\">form.Controls.Add textBox1<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> resultsBox = <\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">new<\/span> ListBox(<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Location = <span style=\"color: blue\">new<\/span> System.Drawing.Point(13, 39),<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; Size = <span style=\"color: blue\">new<\/span> System.Drawing.Size(259, 211))<\/p>\n<p style=\"margin: 0px\">form.Controls.Add resultsBox<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ create a list with common words<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ this might be very large<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> data =<\/p>\n<p style=\"margin: 0px\">&#160; [<span style=\"color: maroon\">&quot;hell&quot;<\/span>; <span style=\"color: maroon\">&quot;Hello&quot;<\/span>; <span style=\"color: maroon\">&quot;Halle&quot;<\/span>; <span style=\"color: maroon\">&quot;Html&quot;<\/span>; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: maroon\">&quot;Bonn&quot;<\/span>; <span style=\"color: maroon\">&quot;Bonjour&quot;<\/span>; <span style=\"color: maroon\">&quot;Steffen&quot;<\/span>]&#160; <\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ create observable for text changes<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> textChanged =<\/p>\n<p style=\"margin: 0px\">&#160; textBox1.TextChanged<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.map (<span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span> textBox1.Text)<\/p>\n<\/p><\/div>\n<p>Now we have to define a base class for observables. This class will help our dictionary lookup function to use the IObservable&lt;T&gt; interface:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\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\">\/\/\/ A Observable base class which notifies <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ all observers in parallel&#160; <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">type<\/span> &#8216;a Observable() =<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">let<\/span> <span style=\"color: blue\">mutable<\/span> observers = []<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ Notifies all observers in parallel about the new value<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">let<\/span> notifyObservers f =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; observers<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Seq.map (<span style=\"color: blue\">fun<\/span> (observer:IObserver&lt;&#8216;a&gt;) \u2013<span style=\"color: blue\">&gt;<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; async { <span style=\"color: blue\">return<\/span> f observer})<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Async.Parallel<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; Async.RunSynchronously<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; |&gt; ignore<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">interface<\/span> IObservable&lt;&#8216;a&gt; <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">member<\/span> observable.Subscribe(observer)&#160; =<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ subscribe observer<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; observers &lt;- observer :: observers<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ create Disposable to unsubscribe observer later<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; {<span style=\"color: blue\">new<\/span> IDisposable <span style=\"color: blue\">with<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">member<\/span> this.Dispose() = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; observers &lt;- <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; observers |&gt; List.filter ((&lt;&gt;) observer)}<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ Notifies all observers in parallel about the new value<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">member<\/span> observable.OnNext value = <\/p>\n<p style=\"margin: 0px\">&#160;&#160; notifyObservers (<span style=\"color: blue\">fun<\/span> observer <span style=\"color: blue\">-&gt;<\/span> observer.OnNext value)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ Notifies all observers in parallel about the error<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ and finishes all observations<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">member<\/span> observable.OnError error = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; notifyObservers (<span style=\"color: blue\">fun<\/span> observer <span style=\"color: blue\">-&gt;<\/span> observer.OnError error)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; observers &lt;- []<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ Notifies all observers in parallel about the completion<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/\/ and finishes all observations<\/span><\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">member<\/span> observable.Completed = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; notifyObservers (<span style=\"color: blue\">fun<\/span> observer <span style=\"color: blue\">-&gt;<\/span> observer.OnCompleted())<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; observers &lt;- []&#160; <\/p>\n<\/p><\/div>\n<p>I hope there will be a similar base class in the .NET Framework 4.0 RTM. <\/p>\n<p>Now we are able to use this class and to build our dictionary lookup observable:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> wordsObservable = <span style=\"color: blue\">new<\/span> Observable.Observable&lt;_&gt;()<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> findWords prefix =<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: blue\">if<\/span> prefix &lt;&gt; <span style=\"color: maroon\">&quot;&quot;<\/span> <span style=\"color: blue\">then<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">let<\/span> prefix&#8217; = prefix.ToUpper()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">for<\/span> word <span style=\"color: blue\">in<\/span> data <span style=\"color: blue\">do<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> word.ToUpper().StartsWith(prefix&#8217;) <span style=\"color: blue\">then<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; wordsObservable.OnNext (prefix,word)<\/p>\n<\/p><\/div>\n<p>The last step is to create observers and subscribe them to the observables:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/ create observers<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> clean = <\/p>\n<p style=\"margin: 0px\">&#160; textChanged <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.subscribe (<span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span> resultsBox.Items.Clear())<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> searchForWords =<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ Every time the text changes <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">&#160; \/\/ we start our wordsObservable to push words<\/span><\/p>\n<p style=\"margin: 0px\">&#160; textChanged <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.subscribe (<span style=\"color: blue\">fun<\/span> text <span style=\"color: blue\">-&gt;<\/span> findWords text)<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> wordFound =<\/p>\n<p style=\"margin: 0px\">&#160; <span style=\"color: green\">\/\/ subscribe to the &quot;word found&quot;-event<\/span><\/p>\n<p style=\"margin: 0px\">&#160; wordsObservable&#160;&#160;&#160; <\/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; (<span style=\"color: blue\">fun<\/span> (_,word) <span style=\"color: blue\">-&gt;<\/span> resultsBox.Items.Add word |&gt; ignore)<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the last article I showed how to filter and combine events via the Reactive Framework and how to deal with errors. This time we will create our own observables. I got the idea for this sample from a very good Expert to Expert video (\u201cReactive Framework (Rx) Under the Hood\u201d) with Erik Meijer and [&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,580,579,578],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/882"}],"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=882"}],"version-history":[{"count":6,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/882\/revisions"}],"predecessor-version":[{"id":888,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/882\/revisions\/888"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=882"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}