<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Luca Bolognese's WebLog : F#</title><link>http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx</link><description>Tags: F#</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>LAgent: an agent framework in F# – Part X – ActiveObject</title><link>http://blogs.msdn.com/lucabol/archive/2009/12/10/lagent-an-agent-framework-in-f-part-x-activeobject.aspx</link><pubDate>Thu, 10 Dec 2009 18:09:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9935251</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9935251.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9935251</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you stare long enough at agents, you start to realize that they are just ‘glorified locks’. They are a convenient programming model to protect a resource from concurrent access. The programming model is convenient because both the client and the server can write their code without worrying about concurrency problems, and yet the program runs in parallel. Protecting a resource sounds a lot like state encapsulation and the concept of state encapsulation is what object orientation is all about.&lt;/p&gt;  &lt;p&gt;So you start thinking if there is a way to enhance vanilla objects to make them agents. You want to reuse all the concepts that you are familiar with (i.e. inheritance, visibility rules, etc…) and you want your clients to call agents as if they were calling normal objects. Obviously, under the cover, the method calls won’t execute immediately, but they would be queued. Let’s look at an example.&lt;/p&gt;  &lt;p&gt;This is our simple counter agent:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;CounterMessage =
| Add &lt;span style="color: blue"&gt;of &lt;/span&gt;int
| Print

&lt;span style="color: blue"&gt;let &lt;/span&gt;counterF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;msg count &lt;span style="color: blue"&gt;-&amp;gt;
    match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
    &lt;/span&gt;| Add(i)    &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;count + i
    | Print     &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The value is %i&amp;quot; &lt;/span&gt;count; count
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;c1 = spawnAgent counterF &lt;span style="color: brown"&gt;0
&lt;/span&gt;c1 &amp;lt;-- Add(&lt;span style="color: brown"&gt;3&lt;/span&gt;)
c1 &amp;lt;—Print&lt;/pre&gt;

&lt;p&gt;As nice as this looks, there are unfamiliar things in this model:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The communication is through messages. This requires packing and unpacking which, albeit easy in F#, is unfamiliar and feels like machinery that we’d like to get rid off. &lt;/li&gt;

  &lt;li&gt;The management of state is bizarre, it gets passed into the lambda and returned from it instead of being represented as fields and properties on the agent &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My best attempt at creating an object-like syntax follows:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Counter() =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;count = &lt;span style="color: brown"&gt;0
    &lt;/span&gt;&lt;span style="color: blue"&gt;member &lt;/span&gt;c.Add x = w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;count &amp;lt;- count + x
        )
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Print () = w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; 
        &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The value is %i&amp;quot; &lt;/span&gt;count
        )&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;c = &lt;span style="color: blue"&gt;new &lt;/span&gt;Counter()
c.Add &lt;span style="color: brown"&gt;3
&lt;/span&gt;c.Print&lt;/pre&gt;

&lt;p&gt;With this syntax, you write your agents like you write your vanilla classes except:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;You need a private field of type &lt;em&gt;WorkQueue&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;You need to write your methods as lambdas passed to the &lt;em&gt;WorkQueue.Queue&lt;/em&gt; function &lt;/li&gt;

  &lt;li&gt;Your methods cannot return values &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most worrisome of these constraints is 2. because you can easily forget about it. If you do forget, then everything compiles just fine, but it doesn’t do what you expect. That’s pure badness. I haven’t found a way to enforce it. This is a place where the language could help me. Other than that, the whole model works rather nicely.&lt;/p&gt;

&lt;p&gt;Regarding the third point, you can concoct a programming model that allows you to return values from your methods. Here it is:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;member &lt;/span&gt;c.CountTask = w.QueueWithTask(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
    &lt;/span&gt;count
    )
&lt;span style="color: blue"&gt;member &lt;/span&gt;c.CountAsync = w.QueueWithAsync(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
    &lt;/span&gt;count
    )&lt;/pre&gt;

&lt;pre class="code"&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;The count using Task is %i&amp;quot; &lt;/span&gt;(c.CountTask.Result)&lt;/pre&gt;

&lt;p&gt;The first method returns a &lt;em&gt;Task;&lt;/em&gt; the second method returns an &lt;em&gt;AsyncResultCell&lt;/em&gt;. Both are ways to represent a &lt;a href="http://en.wikipedia.org/wiki/Future_(programming)"&gt;promise&lt;/a&gt;. The latter allows a natural integration with the async block in F# as in the following code:&lt;/p&gt;

&lt;pre class="code"&gt;Async.RunSynchronously (
            async {
                &lt;span style="color: blue"&gt;let! &lt;/span&gt;count = c.CountAsync
                printfn &lt;span style="color: maroon"&gt;&amp;quot;The countusing Async is %i&amp;quot; &lt;/span&gt;count
            })&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;As for myself, I don’t like methods returning values. Every time I use them, I end up going back and thinking about my problem in a traditional way, aka as method calls that return results, instead of thinking about it in a more actor oriented fashion. I end up waiting for these promises to be materialized and, by doing so, I limit the amount of parallelism that I unleash. As a matter of fact, the whole business of hiding the message passing nature of the programming model is dubious. It makes for a nicer syntax, but you need to make an extra effort in your mind to translate it to what it really is: just message passing with a nice syntactical veneer. I haven’t decided yet which model I like the most.&lt;/p&gt;

&lt;p&gt;You should have a sense of what &lt;em&gt;WorkQueue&lt;/em&gt; is. In essence, it is a &lt;em&gt;Mailbox&lt;/em&gt; of lambdas (look at the red bold code below). &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;WorkQueue() =
    &lt;font color="#ff0000"&gt;&lt;strong&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;workQueue = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;f &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f())&lt;/strong&gt;&lt;/font&gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Queue (f) = workQueue &amp;lt;-- f
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.QueueWithTask f : Task&amp;lt;'T&amp;gt; =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;source = &lt;span style="color: blue"&gt;new &lt;/span&gt;TaskCompletionSource&amp;lt;_&amp;gt;()
        workQueue &amp;lt;-- (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f() |&amp;gt; source.SetResult)
        source.Task
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.QueueWithAsync (f:unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'T) : Async&amp;lt;'T&amp;gt; =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;result = &lt;span style="color: blue"&gt;new &lt;/span&gt;AsyncResultCell&amp;lt;'T&amp;gt;()
        workQueue &amp;lt;-- (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;f() |&amp;gt; result.RegisterResult )
        result.AsyncWaitResult
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Restart () = workQueue &amp;lt;-! Restart
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.Stop () = workQueue &amp;lt;-! Stop
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetErrorHandler(h) =
        &lt;span style="color: blue"&gt;let &lt;/span&gt;managerF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(_, name:string, ex:Exception, _, _, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;h name ex                             
        &lt;span style="color: blue"&gt;let &lt;/span&gt;manager = spawnWorker managerF
        workQueue &amp;lt;-! SetManager manager
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetName(name) = workQueue &amp;lt;-! SetName(name)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetQueueHandler(g) = workQueue &amp;lt;-! SetWorkerHandler(g)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;w.SetTimeoutHandler(timeout, f) = workQueue &amp;lt;-! SetTimeoutHandler(timeout, f)&lt;/pre&gt;

&lt;p&gt;I implemented all the services that are in the message passing model. The two are equivalent as expressing power goes. In case you wonder how a real piece of code looks like using this model, here is an &lt;em&gt;ActiveObject&lt;/em&gt; version of the map reduce algorithm. One of these days, I will gather the strength to go trough this code and explain what it does, but not today :-)&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;#load &lt;/span&gt;&lt;span style="color: maroon"&gt;&amp;quot;AgentSystem.fs&amp;quot;
&lt;/span&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;AgentSystem.LAgent
&lt;span style="color: blue"&gt;open &lt;/span&gt;System
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Collections
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Collections.Generic
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Threading

&lt;span style="color: blue"&gt;type &lt;/span&gt;IOutput&amp;lt;'out_key, 'out_value&amp;gt; =
    &lt;span style="color: blue"&gt;abstract &lt;/span&gt;Reduced: 'out_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt; &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;unit
    &lt;span style="color: blue"&gt;abstract &lt;/span&gt;MapReduceDone: unit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;unit
    
&lt;span style="color: blue"&gt;type &lt;/span&gt;Mapper&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'my_out_key : comparison&amp;gt;&lt;br /&gt;                                                      (map:'in_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'in_value &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'my_out_key * 'out_value&amp;gt;, i, partitionF) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducerTracker: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;controller = Unchecked.defaultof&amp;lt;Controller&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value&amp;gt;&amp;gt;
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducers = Unchecked.defaultof&amp;lt;Reducer&amp;lt;'in_key, 'in_value, 'my_out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Init c reds =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller &amp;lt;- c
            reducers &amp;lt;- reds
            reducerTracker &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Process inKey inValue =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;outKeyValues = map inKey inValue
            outKeyValues |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(outKey, outValue) &lt;span style="color: blue"&gt;-&amp;gt;
                                        let &lt;/span&gt;reducerUsed = partitionF outKey (reducers.Length)
                                        reducerTracker.Set(reducerUsed, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
                                        reducers.[reducerUsed].Add(outKey, outValue)))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Done () =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller.MapDone i reducerTracker)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()            
    
&lt;span style="color: blue"&gt;and &lt;/span&gt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'out_key :&lt;br /&gt;                     comparison&amp;gt;(reduce:'out_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt; &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt;, i, output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;workItems = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;'out_key * 'out_value&amp;gt;()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;controller = Unchecked.defaultof&amp;lt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;&amp;gt;
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.Init c =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;controller &amp;lt;- c)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.StartReduction () =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;workItems
            |&amp;gt; Seq.groupBy fst
            |&amp;gt; Seq.sortBy fst
            |&amp;gt; Seq.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, values) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;(key, reduce key (values |&amp;gt; Seq.map snd)))
            |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, value) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;output.Reduced key value)
            controller.ReductionDone i) 
    &lt;span style="color: blue"&gt;member &lt;/span&gt;r.Add (outKey:'out_key, outValue:'out_value) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;workItems.Add((outKey, outValue)))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()            
                
&lt;span style="color: blue"&gt;and &lt;/span&gt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value &lt;span style="color: blue"&gt;when &lt;/span&gt;'out_key : comparison&amp;gt;(output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;) =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;mapperTracker: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;reducerUsedByMappers: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;reducerDone: BitArray = &lt;span style="color: blue"&gt;null
    let mutable &lt;/span&gt;mappers = Unchecked.defaultof&amp;lt;Mapper&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;let mutable &lt;/span&gt;reducers = Unchecked.defaultof&amp;lt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt; array&amp;gt;
    &lt;span style="color: blue"&gt;let &lt;/span&gt;BAtoSeq (b:BitArray) = [&lt;span style="color: blue"&gt;for &lt;/span&gt;x &lt;span style="color: blue"&gt;in &lt;/span&gt;b &lt;span style="color: blue"&gt;do yield &lt;/span&gt;x]
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Init maps reds =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;mappers &amp;lt;- maps
            reducers &amp;lt;- reds
            mapperTracker &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(mappers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;)
            reducerUsedByMappers &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;)
            reducerDone &amp;lt;- &lt;span style="color: blue"&gt;new &lt;/span&gt;BitArray(reducers.Length, &lt;span style="color: blue"&gt;false&lt;/span&gt;))
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.MapDone (i : int) (reducerTracker : BitArray) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;mapperTracker.Set(i, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
            &lt;span style="color: blue"&gt;let &lt;/span&gt;reducerUsedByMappers = reducerUsedByMappers.Or(reducerTracker)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;not( BAtoSeq mapperTracker |&amp;gt; Seq.exists(&lt;span style="color: blue"&gt;fun &lt;/span&gt;bit &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;bit = &lt;span style="color: blue"&gt;false&lt;/span&gt;)) &lt;span style="color: blue"&gt;then
                &lt;/span&gt;BAtoSeq reducerUsedByMappers |&amp;gt; Seq.iteri (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i r &lt;span style="color: blue"&gt;-&amp;gt; if &lt;/span&gt;r = &lt;span style="color: blue"&gt;true then &lt;/span&gt;reducers.[i].StartReduction ())
                mappers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Stop ())
              )
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.ReductionDone (i: int) : unit =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;reducerDone.Set(i, &lt;span style="color: blue"&gt;true&lt;/span&gt;)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;BAtoSeq reducerDone |&amp;gt; Seq.forall2 (&lt;span style="color: blue"&gt;fun &lt;/span&gt;x y &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;x = y) (BAtoSeq reducerUsedByMappers) &lt;span style="color: blue"&gt;then
                &lt;/span&gt;output.MapReduceDone ()
                reducers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;r &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r.Stop ())
                c.Stop()
             )         
    &lt;span style="color: blue"&gt;member &lt;/span&gt;m.Stop () = w.Stop ()
                
&lt;span style="color: blue"&gt;let &lt;/span&gt;mapReduce   (inputs:seq&amp;lt;'in_key * 'in_value&amp;gt;)
                (map:'in_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'in_value &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_key * 'out_value&amp;gt;)
                (reduce:'out_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt; &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt;)
                (output:IOutput&amp;lt;'out_key, 'out_value&amp;gt;)
                M R partitionF =
                    
    &lt;span style="color: blue"&gt;let &lt;/span&gt;len = inputs |&amp;gt; Seq.length
    &lt;span style="color: blue"&gt;let &lt;/span&gt;M = &lt;span style="color: blue"&gt;if &lt;/span&gt;len &amp;lt; M &lt;span style="color: blue"&gt;then &lt;/span&gt;len &lt;span style="color: blue"&gt;else &lt;/span&gt;M
    
    &lt;span style="color: blue"&gt;let &lt;/span&gt;mappers = Array.init M (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Mapper&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(map, i, partitionF))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;reducers = Array.init R (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;Reducer&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(reduce, i, output))
    &lt;span style="color: blue"&gt;let &lt;/span&gt;controller = &lt;span style="color: blue"&gt;new &lt;/span&gt;Controller&amp;lt;'in_key, 'in_value, 'out_key, 'out_value&amp;gt;(output)
    
    mappers |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Init controller reducers)
    reducers |&amp;gt; Array.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;r &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;r. Init controller )
    controller.Init mappers reducers
    
    inputs |&amp;gt; Seq.iteri (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i (inKey, inValue) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;mappers.[i % M].Process inKey inValue)
    mappers |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;m &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Done ())    

&lt;span style="color: blue"&gt;let &lt;/span&gt;partitionF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key M &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;abs(key.GetHashCode()) % M 

&lt;span style="color: blue"&gt;let &lt;/span&gt;map = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(fileName:string) (fileContent:string) &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;l = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * int&amp;gt;()
            &lt;span style="color: blue"&gt;let &lt;/span&gt;wordDelims = [|&lt;span style="color: maroon"&gt;' '&lt;/span&gt;;&lt;span style="color: maroon"&gt;','&lt;/span&gt;;&lt;span style="color: maroon"&gt;';'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'.'&lt;/span&gt;;&lt;span style="color: maroon"&gt;':'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'?'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'!'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'('&lt;/span&gt;;&lt;span style="color: maroon"&gt;')'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\n'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\t'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\f'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\r'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\b'&lt;/span&gt;|]
            fileContent.Split(wordDelims) |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;word &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;l.Add((word, &lt;span style="color: brown"&gt;1&lt;/span&gt;)))
            l :&amp;gt; seq&amp;lt;string * int&amp;gt;
                                  
&lt;span style="color: blue"&gt;let &lt;/span&gt;reduce = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key (values:seq&amp;lt;int&amp;gt;) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;[values |&amp;gt; Seq.sum] |&amp;gt; seq&amp;lt;int&amp;gt;

&lt;span style="color: blue"&gt;let &lt;/span&gt;printer () =
  { &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
        member &lt;/span&gt;o.Reduced key values = printfn &lt;span style="color: maroon"&gt;&amp;quot;%A %A&amp;quot; &lt;/span&gt;key values
        &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () = printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&lt;/span&gt;}
    
&lt;span style="color: blue"&gt;let &lt;/span&gt;testInput =&lt;br /&gt;     [&lt;span style="color: maroon"&gt;&amp;quot;File1&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going to the airport when I saw someone crossing&amp;quot;&lt;/span&gt;; &lt;span style="color: maroon"&gt;&amp;quot;File2&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going home when I saw you coming toward me&amp;quot;&lt;/span&gt;]   
mapReduce testInput map reduce (printer ()) &lt;span style="color: brown"&gt;2 2 &lt;/span&gt;partitionF

&lt;span style="color: blue"&gt;open &lt;/span&gt;System.IO
&lt;span style="color: blue"&gt;open &lt;/span&gt;System.Text

&lt;span style="color: blue"&gt;let &lt;/span&gt;gatherer(step) =
  &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
  &lt;span style="color: blue"&gt;let &lt;/span&gt;data = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * int&amp;gt;()
  &lt;span style="color: blue"&gt;let &lt;/span&gt;counter = ref &lt;span style="color: brown"&gt;0 
  &lt;/span&gt;{ &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
        member &lt;/span&gt;o.Reduced key values =
            w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                if &lt;/span&gt;!counter % step = &lt;span style="color: brown"&gt;0 &lt;/span&gt;&lt;span style="color: blue"&gt;then
                    &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Processed %i words. Now processing %s&amp;quot; &lt;/span&gt;!counter key 
                data.Add((key, values |&amp;gt; Seq.hd))
                counter := !counter + &lt;span style="color: brown"&gt;1&lt;/span&gt;)
        &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () =
            w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                &lt;/span&gt;data
                |&amp;gt; Seq.distinctBy (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;key.ToLower())
                |&amp;gt; Seq.filter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;not(key = &lt;span style="color: maroon"&gt;&amp;quot;&amp;quot; &lt;/span&gt;|| key = &lt;span style="color: maroon"&gt;&amp;quot;\&amp;quot;&amp;quot; &lt;/span&gt;|| (fst (Double.TryParse(key)))))
                |&amp;gt; Seq.to_array
                |&amp;gt; Array.sortBy snd
                |&amp;gt; Array.rev
                |&amp;gt; Seq.take &lt;span style="color: brown"&gt;20
                &lt;/span&gt;|&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, value) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A\t\t%A&amp;quot; &lt;/span&gt;key value)
                printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&lt;/span&gt;)           
        }
                        
&lt;span style="color: blue"&gt;let &lt;/span&gt;splitBook howManyBlocks fileName =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;buffers = Array.init howManyBlocks (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; new &lt;/span&gt;StringBuilder())
    fileName
    |&amp;gt; File.ReadAllLines
    |&amp;gt; Array.iteri (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i line &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;buffers.[i % (howManyBlocks)].Append(line) |&amp;gt; ignore)
    buffers

&lt;span style="color: blue"&gt;let &lt;/span&gt;blocks1 = &lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\kjv10.txt&amp;quot; &lt;/span&gt;|&amp;gt; splitBook &lt;span style="color: brown"&gt;100
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;blocks2 = &lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\warandpeace.txt&amp;quot; &lt;/span&gt;|&amp;gt; splitBook &lt;span style="color: brown"&gt;100
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;input =
    blocks1
    |&amp;gt; Array.append blocks2
    |&amp;gt; Array.mapi (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;i.ToString(), b.ToString())
        
&lt;span style="color: green"&gt;//mapReduce input map reduce (gatherer(1000)) 20 20 partitionF

&lt;/span&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;BookSplitter () =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;blocks = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * string&amp;gt;()
    &lt;span style="color: blue"&gt;member &lt;/span&gt;b.Split howManyBlocks fileName =
            &lt;span style="color: blue"&gt;let &lt;/span&gt;b =
                fileName
                |&amp;gt; splitBook howManyBlocks
                |&amp;gt; Array.mapi (&lt;span style="color: blue"&gt;fun &lt;/span&gt;i b &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;i.ToString(), b.ToString())
            blocks.AddRange(b)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;b.Blocks () =
            blocks.ToArray() :&amp;gt; seq&amp;lt;string * string&amp;gt;

&lt;span style="color: blue"&gt;type &lt;/span&gt;WordCounter () =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;w = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
    &lt;span style="color: blue"&gt;let &lt;/span&gt;words = &lt;span style="color: blue"&gt;new &lt;/span&gt;Dictionary&amp;lt;string,int&amp;gt;()
    &lt;span style="color: blue"&gt;let &lt;/span&gt;worker(wordCounter:WordCounter, ev:EventWaitHandle) =
          &lt;span style="color: blue"&gt;let &lt;/span&gt;w1 = &lt;span style="color: blue"&gt;new &lt;/span&gt;WorkQueue()
          { &lt;span style="color: blue"&gt;new &lt;/span&gt;IOutput&amp;lt;string, int&amp;gt; &lt;span style="color: blue"&gt;with
                member &lt;/span&gt;o.Reduced key values =
                    w1.Queue (&lt;span style="color: blue"&gt;fun&lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;wordCounter.AddWord key (values |&amp;gt; Seq.hd))
                &lt;span style="color: blue"&gt;member &lt;/span&gt;o.MapReduceDone () =
                    w1.Queue(&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;ev.Set() |&amp;gt; ignore)
           }
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.AddWord word count =
            &lt;span style="color: blue"&gt;let &lt;/span&gt;exist, value = words.TryGetValue(word)
            &lt;span style="color: blue"&gt;if &lt;/span&gt;exist &lt;span style="color: blue"&gt;then
                &lt;/span&gt;words.[word] &amp;lt;- value + count
            &lt;span style="color: blue"&gt;else
                &lt;/span&gt;words.Add(word, count)
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Add fileName =
        w.Queue (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;s = &lt;span style="color: blue"&gt;new &lt;/span&gt;BookSplitter()
            fileName |&amp;gt; s.Split &lt;span style="color: brown"&gt;100
            &lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;ev = &lt;span style="color: blue"&gt;new &lt;/span&gt;EventWaitHandle(&lt;span style="color: blue"&gt;false&lt;/span&gt;, EventResetMode.AutoReset)
            &lt;span style="color: blue"&gt;let &lt;/span&gt;blocks = s.Blocks ()
            mapReduce blocks map reduce (worker(c, ev)) &lt;span style="color: brown"&gt;20 20 &lt;/span&gt;partitionF
            ev.WaitOne() |&amp;gt; ignore
            )  
    &lt;span style="color: blue"&gt;member &lt;/span&gt;c.Words =
        w.QueueWithAsync (&lt;span style="color: blue"&gt;fun &lt;/span&gt;() &lt;span style="color: blue"&gt;-&amp;gt;
            &lt;/span&gt;words |&amp;gt; Seq.to_array |&amp;gt; Array.map (&lt;span style="color: blue"&gt;fun &lt;/span&gt;kv &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;kv.Key, kv.Value)
        )    

&lt;span style="color: blue"&gt;let &lt;/span&gt;wc = &lt;span style="color: blue"&gt;new &lt;/span&gt;WordCounter()
wc.Add (&lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\kjv10.txt&amp;quot;&lt;/span&gt;)
wc.Add (&lt;span style="color: blue"&gt;__SOURCE_DIRECTORY__ &lt;/span&gt;+ &lt;span style="color: maroon"&gt;&amp;quot;\warandpeace.txt&amp;quot;&lt;/span&gt;)

&lt;span style="color: blue"&gt;let &lt;/span&gt;wordsToPrint = async {
                    &lt;span style="color: blue"&gt;let! &lt;/span&gt;words = wc.Words
                    &lt;span style="color: blue"&gt;return &lt;/span&gt;words
                        |&amp;gt; Seq.distinctBy (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;key.ToLower())
                        |&amp;gt; Seq.filter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, _) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;not(key = &lt;span style="color: maroon"&gt;&amp;quot;&amp;quot; &lt;/span&gt;|| key = &lt;span style="color: maroon"&gt;&amp;quot;\&amp;quot;&amp;quot; &lt;/span&gt;|| (fst (Double.TryParse(key)))))
                        |&amp;gt; Seq.to_array
                        |&amp;gt; Array.sortBy snd
                        |&amp;gt; Array.rev
                        |&amp;gt; Seq.take &lt;span style="color: brown"&gt;20
                        &lt;/span&gt;|&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(key, value) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A\t\t%A&amp;quot; &lt;/span&gt;key value)}


Async.RunSynchronously wordsToPrint
                        
Thread.Sleep(&lt;span style="color: brown"&gt;15000&lt;/span&gt;)
printfn &lt;span style="color: maroon"&gt;&amp;quot;Closed session&amp;quot;               
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9935251" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>Luca at PDC 2009 next week</title><link>http://blogs.msdn.com/lucabol/archive/2009/11/13/luca-at-pdc-2009-next-week.aspx</link><pubDate>Fri, 13 Nov 2009 18:49:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9922139</guid><dc:creator>lucabol</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9922139.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9922139</wfw:commentRss><description>&lt;p&gt;I’ll be in Los Angeles next week for PDC 2009. My session is called “&lt;a href="http://microsoftpdc.com/Sessions/FT11"&gt;Future Directions for C# and Visual Basic&lt;/a&gt;” and it comes on Tuesday immediately after the first keynote.&lt;/p&gt;  &lt;p&gt;I’m planning on spending the first half of the session talking about the biggest trends influencing C# and VB. The second part will be about more future looking features we are playing with these days.&lt;/p&gt;  &lt;p&gt;My deck has just two slides, as always. It’s all about watching me typing code on stage, hoping that I make crazy errors …&lt;/p&gt;  &lt;p&gt;There are several other interesting language related sessions at PDC. Here is a list of them (please notice that the times might change). Also feel free to drop by the languages booth and chat. My team and I will be there most of the time.&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;&lt;b&gt;Day&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;&lt;b&gt;Time&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Title&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;&lt;b&gt;Presenter&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;&lt;b&gt;Room&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:00 - 12:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Future Directions for C# and Visual Basic&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Luca Bolognese&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Hall F&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:00 - 12:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Accelerated Windows Application Development with Microsoft Visual C++ 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Boris Jabes&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408B&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:30 - 13:15&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Dynamic Binding in C# 4&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Mads Torgersen&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Hall F&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:30 - 13:15&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Using Dynamic Languages to Build Scriptable Applications&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Dino Viehland&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;403AB&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:30 - 14:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;C++ Forever: Interactive Applications in the Age of Manycore&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Rick Molloy&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515B&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;16:30 - 17:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Manycore and the Microsoft .NET Framework 4: A Match Made in Microsoft Visual Studio 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Stephen Toub&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;502A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Tues 11/17&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;16:30 - 17:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Code Contracts and Pex: Power Charge Your Assertions and Unit Tests&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Mike Barnett, Nikolai Tillmann&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:30 - 12:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Perspectives on the Future of Programming&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Panel&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:00 - 13:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;F# for Architects – Hitting the Sweet Spot&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Chris Smith&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;VS and .NET Pavillion&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Code Like the Wind with Microsoft Visual Basic 2010&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Lucian Wischik&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall D&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Future of Garbage Collection&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Patrick Dussud&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Wed 11/18&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;13:00 - 13:45&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Project Code Name “M”: The Data and Modeling Language&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Don Box, Jeff Pinkston&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;408A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;08:30 - 09:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;PLINQ: LINQ, but Faster!&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Ed Essey, Igor Ostrovsky&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;10:00 - 11:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;A Lap around Microsoft Visual Studio 2010 for the Visual Basic Developer &lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Lisa Feigenbaum&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;VS and .NET Pavillion&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;10:00 - 11:00&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Axum: A .NET Language for Safe and Scalable Concurrency&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Niklas Gustafsson&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;11:30 - 12:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;F# for Parallel and Asynchronous Programming&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Luke Hoban&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;515A&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:45 - 13:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Visual C# IDE Tips and Tricks&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;DJ Park&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall D&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="62"&gt;         &lt;p&gt;Thu&lt;/p&gt;          &lt;p&gt;11/19&lt;b&gt;&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="96"&gt;         &lt;p&gt;12:45 - 13:30&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="502"&gt;         &lt;p&gt;&lt;b&gt;Microsoft Visual Basic IDE Tips and Tricks&lt;/b&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="147"&gt;         &lt;p&gt;Dustin Campbell&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top" width="117"&gt;         &lt;p&gt;Petree Hall C&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9922139" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/.NET+Futures/default.aspx">.NET Futures</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>LAgent: an agent framework in F# – Part VIII - Implementing MapReduce (user model)</title><link>http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx</link><pubDate>Fri, 04 Sep 2009 20:57:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9891606</guid><dc:creator>lucabol</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9891606.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9891606</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;p&gt;For this post I use a newer version of the framework that I just uploaded on CodeGallery. In the process of using LAgent I grew more and more unhappy with the weakly typed way of sending messages. The code that implements that feature is nasty: full of upcasts and downcasts. I was losing faith in it. Bugs were cropping up in all sorts of scenarios (i.e. using generic union types as messages).&lt;/p&gt;  &lt;p&gt;In the end I decided to re-architecture the framework so to make it strongly typed. In essence now each agent can just receive messages of a single type. The limitations that this design choice introduces (i.e. more limited hot swapping) are compensated by the catching of errors at compile time and the streamlining of the code. I left the old framework on the site in case you disagree with me.&lt;/p&gt;  &lt;p&gt;In any case, today’s post is about &lt;em&gt;MapReduce&lt;/em&gt;. It assumes that you know what it is (link to the original Google paper that served as inspiration is here: &lt;a title="Google Research Publication- MapReduce" href="http://labs.google.com/papers/mapreduce.html"&gt;Google Research Publication- MapReduce&lt;/a&gt;). What would it take to implement an in-memory &lt;em&gt;MapReduce&lt;/em&gt; using my agent framework?&lt;/p&gt;  &lt;p&gt;Let’s start with the user model.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;mapReduce   (inputs:seq&amp;lt;'in_key * 'in_value&amp;gt;)
                (map:'in_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;'in_value &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_key * 'out_value&amp;gt;)
                (reduce:'out_key &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'out_value&amp;gt; &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;seq&amp;lt;'reducedValues&amp;gt;)
                outputAgent
                M R partitionF =                &lt;/pre&gt;

&lt;p&gt;&lt;em&gt;mapReduce&lt;/em&gt; takes seven parameters:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;u&gt;inputs&lt;/u&gt;: a sequence of input key/value pairs. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;map&lt;/u&gt;: this function operates on each input key/value pair. It&amp;#160; returns a sequence of output key/value pairs. The type of the output sequence can be different from the type of the inputs. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;reduce&lt;/u&gt;: this function operates on an output key and all the values associated with it. It returns a sequence of reduced values (i.e. the average of all the values for this key) &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;ouputAgent&lt;/u&gt;: this is the agent that gets notified every time a new output key has been reduced and at the end when all the operation ends. &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;M&lt;/u&gt;: how many mapper agents to instantiate &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;R&lt;/u&gt;: how many reducer agents to instantiate &lt;/li&gt;

  &lt;li&gt;&lt;u&gt;partitionF&lt;/u&gt;: the partition function used to choose which of the reducers is associated with a key &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at how to use this function to find how often each word is used in a set of files. First a simple partition function can be defined as:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;partitionF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key M &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;abs(key.GetHashCode()) % M &lt;/pre&gt;

&lt;p&gt;Given a key and some buckets, it picks one of the buckets. Its type is: ‘a –&amp;gt; int –&amp;gt; int, so it’s fairly reusable.&lt;/p&gt;

&lt;p&gt;Let’s also create a basic agent that just prints out the reduced values:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;printer = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt;
                            match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                            &lt;/span&gt;| Reduced(key, value)   &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%A %A&amp;quot; &lt;/span&gt;key value
                            | MapReduceDone         &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;All done!!&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;The agent gets notified whenever a new key is reduced or the algorithm ends. It is useful to be notified immediately instead of waiting for everything to be done. If I hadn’t written this code using agents I would have not realized that possibility. I would simply have framed the problem as a function that takes an input and returns an output. Agents force you to think explicitly about the parallelism in your app. That’s a good thing.&lt;/p&gt;

&lt;p&gt;The mapping function simply split the content of a file into words and adds a word/1 pair to the list. I know that there are much better ways to do this (i.e. regular expressions for the parsing and summing words counts inside the function), but I wanted to test the basic framework capabilities and doing it this way does it better.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;map = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(fileName:string) (fileContent:string) &lt;span style="color: blue"&gt;-&amp;gt;
            let &lt;/span&gt;l = &lt;span style="color: blue"&gt;new &lt;/span&gt;List&amp;lt;string * int&amp;gt;()
            &lt;span style="color: blue"&gt;let &lt;/span&gt;wordDelims = [|&lt;span style="color: maroon"&gt;' '&lt;/span&gt;;&lt;span style="color: maroon"&gt;','&lt;/span&gt;;&lt;span style="color: maroon"&gt;';'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'.'&lt;/span&gt;;&lt;span style="color: maroon"&gt;':'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'?'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'!'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'('&lt;/span&gt;;&lt;span style="color: maroon"&gt;')'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\n'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\t'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\f'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\r'&lt;/span&gt;;&lt;span style="color: maroon"&gt;'\b'&lt;/span&gt;|]
            fileContent.Split(wordDelims) |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;word &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;l.Add((word, &lt;span style="color: brown"&gt;1&lt;/span&gt;)))
            l :&amp;gt; seq&amp;lt;string * int&amp;gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The reducer function simply sums the various word statistics sent by the mappers:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;reduce = &lt;span style="color: blue"&gt;fun &lt;/span&gt;key (values:seq&amp;lt;int&amp;gt;) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;[values |&amp;gt; Seq.sum] |&amp;gt; seq&amp;lt;int&amp;gt;&lt;/pre&gt;

&lt;p&gt;Now we can create some fake input to check that it works:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;testInput = [&lt;span style="color: maroon"&gt;&amp;quot;File1&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going to the airport when I saw someone crossing&amp;quot;&lt;/span&gt;;&lt;br /&gt;                               &lt;span style="color: maroon"&gt;&amp;quot;File2&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;I was going home when I saw you coming toward me&amp;quot;&lt;/span&gt;]   &lt;/pre&gt;

&lt;p&gt;And execute the &lt;em&gt;mapReduce&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;mapReduce testInput map reduce printer &lt;span style="color: brown"&gt;2 2 &lt;/span&gt;partitionF&lt;/pre&gt;

&lt;p&gt;On my machine I get the following. You might get a different order because of the async/parallel processing involved. If I wanted a stable order I would need to change the &lt;em&gt;printer&lt;/em&gt; agent to cache results on &lt;em&gt;Reduced&lt;/em&gt; and process them on &lt;em&gt;MapReduceDone&lt;/em&gt; (see next post).&lt;/p&gt;

&lt;p&gt;&amp;quot;I&amp;quot; [4] 
  &lt;br /&gt;&amp;quot;crossing&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;going&amp;quot; [2] 

  &lt;br /&gt;&amp;quot;home&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;me&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;the&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;toward&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;airport&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;coming&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;saw&amp;quot; [2] 

  &lt;br /&gt;&amp;quot;someone&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;to&amp;quot; [1] 

  &lt;br /&gt;&amp;quot;was&amp;quot; [2] 

  &lt;br /&gt;&amp;quot;when&amp;quot; [2] 

  &lt;br /&gt;&amp;quot;you&amp;quot; [1]&lt;/p&gt;

&lt;p&gt;In the next post we’ll process some real books …&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9891606" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – part VII – An auction application</title><link>http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx</link><pubDate>Fri, 10 Jul 2009 23:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9682539</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9682539.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9682539</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;p&gt;Here is an application that uses the framework we have been creating. It is an auction application and it is described in more detail &lt;a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/05/20/f-actors-revisited.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Let’s go through it.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;AuctionMessage =
  | Offer &lt;span style="color: blue"&gt;of &lt;/span&gt;int * AsyncAgent &lt;span style="color: green"&gt;// Make a bid
  &lt;/span&gt;| Inquire &lt;span style="color: blue"&gt;of &lt;/span&gt;AsyncAgent     &lt;span style="color: green"&gt;// Check the status
&lt;/span&gt;&lt;span style="color: blue"&gt;and &lt;/span&gt;AuctionReply =
  | StartBidding
  | Status &lt;span style="color: blue"&gt;of &lt;/span&gt;int * DateTime &lt;span style="color: green"&gt;// Asked sum and expiration
  &lt;/span&gt;| BestOffer                &lt;span style="color: green"&gt;// Ours is the best offer
  &lt;/span&gt;| BeatenOffer &lt;span style="color: blue"&gt;of &lt;/span&gt;int       &lt;span style="color: green"&gt;// Yours is beaten by another offer
  &lt;/span&gt;| AuctionConcluded &lt;span style="color: blue"&gt;of      &lt;/span&gt;&lt;span style="color: green"&gt;// Auction concluded
      &lt;/span&gt;AsyncAgent * AsyncAgent
  | AuctionFailed            &lt;span style="color: green"&gt;// Failed without any bids
  &lt;/span&gt;| AuctionOver              &lt;span style="color: green"&gt;// Bidding is closed
  
&lt;/span&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;timeToShutdown = 3000
&lt;span style="color: blue"&gt;let &lt;/span&gt;bidIncrement = 10 &lt;/pre&gt;

&lt;p&gt;This is the format of the messages that the clients can send and the action agent can reply to. F# is really good at this sort of thing. First, we need an auction agent:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;auctionAgent seller minBid closing =
    &lt;span style="color: blue"&gt;let &lt;/span&gt;agent = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg (isConcluded, maxBid, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                            match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                            &lt;/span&gt;| Offer (_, client) &lt;span style="color: blue"&gt;when &lt;/span&gt;isConcluded &lt;span style="color: blue"&gt;-&amp;gt;
                                &lt;/span&gt;client &amp;lt;-- AuctionOver
                                (isConcluded, maxBid, maxBidder)
                            | Offer(bid, client) &lt;span style="color: blue"&gt;when &lt;/span&gt;not(isConcluded) &lt;span style="color: blue"&gt;-&amp;gt;
                                if &lt;/span&gt;bid &amp;gt;= maxBid + bidIncrement &lt;span style="color: blue"&gt;then
                                    if &lt;/span&gt;maxBid &amp;gt;= minBid &lt;span style="color: blue"&gt;then &lt;/span&gt;maxBidder &amp;lt;-- BeatenOffer bid                  
                                    client &amp;lt;-- BestOffer
                                    (isConcluded, bid, client)
                                &lt;span style="color: blue"&gt;else
                                    &lt;/span&gt;client &amp;lt;-- BeatenOffer maxBid
                                    (isConcluded, maxBid, maxBidder)
                            | Inquire client    &lt;span style="color: blue"&gt;-&amp;gt;
                                &lt;/span&gt;client &amp;lt;-- Status(maxBid, closing)
                                (isConcluded, maxBid, maxBidder))
                            (&lt;span style="color: blue"&gt;false&lt;/span&gt;, (minBid - bidIncrement), spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;()))                             &lt;/pre&gt;

&lt;p&gt;Notice that, if the action is concluded, the agent replies to offers by sending an &lt;em&gt;AuctionOver&lt;/em&gt; message. If the auction is still open, then, in case the bid is higher than the max, it sets a new max and notify the two parties involved; otherwise it notifies the bidder that the offer wasn’t successful. Also you can ask for the status of the auction.&lt;/p&gt;

&lt;p&gt;This is what the code above says. Maybe the code is simpler than words. Anyhow, we need to treat the case where no message is received for some amount of time.&lt;/p&gt;

&lt;pre class="code"&gt;agent &amp;lt;-- SetTimeoutHandler
            (closing - DateTime.Now).Milliseconds
            (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(isConcluded: bool, maxBid, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                if &lt;/span&gt;maxBid &amp;gt;= minBid &lt;span style="color: blue"&gt;then
                  let &lt;/span&gt;reply = AuctionConcluded(seller, maxBidder)
                  maxBidder &amp;lt;-- reply
                  seller &amp;lt;-- reply
                &lt;span style="color: blue"&gt;else &lt;/span&gt;seller &amp;lt;-- AuctionFailed
                agent &amp;lt;-- SetTimeoutHandler
                    timeToShutdown
                    (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(_:bool, _:int,_:AsyncAgent) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;StopProcessing)
                ContinueProcessing (&lt;span style="color: blue"&gt;true&lt;/span&gt;, maxBid, maxBidder))   
agent            &lt;/pre&gt;

&lt;p&gt;We start by waiting for the amount of time to the closing of the auction. If we get no messages, then two things might happen: we have an offer that is more than the minimum or we don’t. If we do, we tell everyone that it’s finished. Otherwise, we tell the seller that its item wasn’t successful.&amp;#160; In any case, we prepare the agent to shutdown by setting its next timeout to be &lt;em&gt;timeoutToShutdown&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is interesting that we set the timeout handler inside the timeout handler. This is not a problem because of the nature of message processing (aka it processes one message at the time).&lt;/p&gt;

&lt;p&gt;We then need a bunch of of symbols …&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;module &lt;/span&gt;Auction =
  &lt;span style="color: blue"&gt;let &lt;/span&gt;random = &lt;span style="color: blue"&gt;new &lt;/span&gt;Random()
  
  &lt;span style="color: blue"&gt;let &lt;/span&gt;minBid = 100
  &lt;span style="color: blue"&gt;let &lt;/span&gt;closing = DateTime.Now.AddMilliseconds 10000.
  
  &lt;span style="color: blue"&gt;let &lt;/span&gt;seller = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(msg:AuctionReply) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;())
  &lt;span style="color: blue"&gt;let &lt;/span&gt;auction = auctionAgent seller minBid closing&lt;/pre&gt;

&lt;p&gt;Not a very smart seller we have here … Next up is our definition of a client.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;c = spawnAgent (
                &lt;span style="color: blue"&gt;fun &lt;/span&gt;msg (max, current) &lt;span style="color: blue"&gt;-&amp;gt;
                    let &lt;/span&gt;processBid (aMax, aCurrent) =
                        &lt;span style="color: blue"&gt;if &lt;/span&gt;aMax &amp;gt;= top &lt;span style="color: blue"&gt;then
                            &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;too high for me&amp;quot;
                            &lt;/span&gt;(aMax, aCurrent)
                        &lt;span style="color: blue"&gt;elif &lt;/span&gt;aCurrent &amp;lt; aMax &lt;span style="color: blue"&gt;then
                              let &lt;/span&gt;aCurrent = aMax + increment
                              Thread.Sleep (1 + random.Next 1000)
                              auction &amp;lt;-- Offer(aCurrent, c)
                              (aMax, aCurrent)
                        &lt;span style="color: blue"&gt;else &lt;/span&gt;(aMax, aCurrent)                       
                    &lt;span style="color: blue"&gt;match &lt;/span&gt;msg &lt;span style="color: blue"&gt;with
                    &lt;/span&gt;| StartBidding      &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;auction &amp;lt;-- Inquire c
                        (max, current)
                    | Status(maxBid,_)  &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;status(%d)&amp;quot; &lt;/span&gt;maxBid
                        &lt;span style="color: blue"&gt;let &lt;/span&gt;s = processBid (maxBid, current)
                        c &amp;lt;-- SetTimeoutHandler timeToShutdown (&lt;span style="color: blue"&gt;fun &lt;/span&gt;_ &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;StopProcessing) 
                        s
                    | BestOffer &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;bestOffer(%d)&amp;quot; &lt;/span&gt;current
                        processBid(max, current)
                    | BeatenOffer maxBid &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &amp;lt;| sprintf &lt;span style="color: maroon"&gt;&amp;quot;beatenOffer(%d)&amp;quot; &lt;/span&gt;maxBid
                        processBid(maxBid, current)
                    | AuctionConcluded(seller, maxBidder) &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;auctionConcluded&amp;quot;
                        &lt;/span&gt;c &amp;lt;-- Stop
                        (max, current)
                    | AuctionOver &lt;span style="color: blue"&gt;-&amp;gt;
                        &lt;/span&gt;log &lt;span style="color: maroon"&gt;&amp;quot;auctionOver&amp;quot;
                        &lt;/span&gt;c &amp;lt;-- Stop
                        (max, current))
                 (0,0)
c&lt;/pre&gt;

&lt;p&gt;Something that I like about agents is the fact that you need to understand just small snippets of code at the time. For example, you can read the processing for BestOffer and figure out if it makes sense.&amp;#160; I have an easy time personalizing them as in : “Ok, the guy just got a notification that there has been a better offer, what is he going to do next?”.&lt;/p&gt;

&lt;p&gt;The code should be self explanatory for the most part. In essence, if you can offer more, do it otherwise wait for the auction to end. I’m not even sure the processing is completely right. I confess I’m just trying to do the same as Matthews code from the link above.&lt;/p&gt;

&lt;p&gt;We can then start up the whole thing and enjoy the cool output.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;open &lt;/span&gt;Auction

(client 1 20 200) &amp;lt;-- StartBidding
(client 2 10 300) &amp;lt;-- StartBidding
(client 3 30 150) &amp;lt;-- StartBidding
Console.ReadLine() |&amp;gt; ignore  &lt;/pre&gt;

&lt;p&gt;Now for the nasty part. Implementing the framework.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9682539" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part VI – Hot swapping of code (and something silly)</title><link>http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx</link><pubDate>Fri, 03 Jul 2009 22:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649341</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649341.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649341</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt;&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Hot swapping of code&lt;/h4&gt;  &lt;p&gt;Let’s get back a couple of steps and consider what happens when you get an error. Sure, your agent will continue processing messages, but it might be doing the wrong thing. Your message handling code might be buggy.&lt;/p&gt;  &lt;p&gt;Ideally you’d want to patch things on the fly. You’d want to replace the message processing code for an agent without stopping it.&lt;/p&gt;  &lt;p&gt;Here is how you do it:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter2 = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i&amp;quot; &lt;/span&gt;state (state + msg);&lt;br /&gt;                                                                              state + msg) 0
counter2 &amp;lt;-- 2
                                         
counter2 &amp;lt;-- SetAgentHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state –&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;                &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i via multiplication&amp;quot; &lt;/span&gt;state (state * msg); msg * state)
counter2 &amp;lt;-- 3&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Which generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 2 
      &lt;br /&gt;From 2 to 6 via multiplication&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After the agent receives a &lt;em&gt;SetAgentHandler&lt;/em&gt; message, it switch from a ‘+’ agent to a ‘*’ agent on the fly!! All the messages that come after that one gets multiplied to the state. Also, the state is preserved between changes in behavior.&lt;/p&gt;

&lt;p&gt;It might not be immediately apparent how to load a function at runtime, but it is really simple. Imagine that I get the data on the function to load from somewhere (i.e. a management console UI).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;assemblyNameFromSomewhere, typeNameFromSomewhere, methodNameFromSomewhere = &lt;br /&gt;                                                &lt;span style="color: maroon"&gt;&amp;quot;mscorlib.dll&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;System.Console&amp;quot;&lt;/span&gt;, &lt;span style="color: maroon"&gt;&amp;quot;WriteLine&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;I can then use it to dynamically load a message handler (in this case &lt;em&gt;Console.Writeline&lt;/em&gt;).&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;a = Assembly.Load(assemblyNameFromSomewhere)
&lt;span style="color: blue"&gt;let &lt;/span&gt;c = a.GetType(typeNameFromSomewhere)
&lt;span style="color: blue"&gt;let &lt;/span&gt;m = c.GetMethod(methodNameFromSomewhere, [|&lt;span style="color: maroon"&gt;&amp;quot;&amp;quot;&lt;/span&gt;.GetType()|])
&lt;span style="color: blue"&gt;let &lt;/span&gt;newF = &lt;span style="color: blue"&gt;fun &lt;/span&gt;(msg:string) (state:obj) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;m.Invoke(&lt;span style="color: blue"&gt;null&lt;/span&gt;, [| (msg:&amp;gt;obj) |])&lt;/pre&gt;

&lt;p&gt;And then it is as simple as posting a &lt;em&gt;SetAgentHandler&lt;/em&gt;.&lt;/p&gt;

&lt;pre class="code"&gt;counter2 &amp;lt;-- SetAgentHandler(newF)
counter2 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;blah&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now our &lt;em&gt;counter2&lt;/em&gt; agent has become an echo agent on the fly, having loaded &lt;em&gt;Console.WriteLine&lt;/em&gt; dynamically. Note how the agent moved from being a ‘+’ agent taking integers to being a ‘*’ agent taking integers to being an ‘echo’ agent taking strings. And it didn’t stop processing messages for the whole time.&lt;/p&gt;

&lt;p&gt;Obviously, you can do the same thing with workers:&lt;/p&gt;

&lt;pre class="code"&gt;echo &amp;lt;-- SetWorkerHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;I'm an echo and I say: %s&amp;quot; &lt;/span&gt;msg)
echo &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;And parallelWorkers:&lt;/p&gt;

&lt;pre class="code"&gt;parallelEcho &amp;lt;-- SetWorkerHandler(&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint (&lt;span style="color: maroon"&gt;&amp;quot;I'm new and &amp;quot; &lt;/span&gt;+ msg))
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;parallelEcho &amp;lt;-- msg)&lt;/pre&gt;

&lt;h4&gt;A silly interlude&lt;/h4&gt;

&lt;p&gt;As a way to show some agents talking to each other, here is a simple program that simulates marital interactions (of the worst kind):&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let rec &lt;/span&gt;husband = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(To, msg) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Husband says: %s&amp;quot; &lt;/span&gt;msg; To &amp;lt;-- msg)
&lt;span style="color: blue"&gt;let rec &lt;/span&gt;wife = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Wife says: screw you and your '%s'&amp;quot; &lt;/span&gt;msg)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;But darling ...&amp;quot;&lt;/span&gt;)
husband &amp;lt;-- (wife, &lt;span style="color: maroon"&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Husband says: Hello 
      &lt;br /&gt;Husband says: But darling ... 

      &lt;br /&gt;Wife says: screw you and your 'Hello' 

      &lt;br /&gt;Wife says: screw you and your 'But darling ...' 

      &lt;br /&gt;Husband says: ok 

      &lt;br /&gt;Wife says: screw you and your 'ok'&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yes, you cannot expect messages to be in the right sequence … Next up is an auction application.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649341" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part V – Timeout management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx</link><pubDate>Fri, 26 Jun 2009 21:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649246</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649246.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649246</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Timeout management&lt;/h4&gt;  &lt;p&gt;Timeouts are very important in message based systems. In essence, if you are not getting messages for a certain period of time, that usually means something. It might be that something crashed, that other agents think that you are not online, or any other number of things. Hence the need to set timeouts and react when they are triggered.&lt;/p&gt;  &lt;p&gt;You do that by writing the following:&lt;/p&gt;  &lt;pre class="code"&gt;counter1 &amp;lt;--SetTimeoutHandler 1000 &lt;br /&gt;            (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;I'm still waiting for a message in state %A, come on ...&amp;quot; &lt;br /&gt;                                                            &lt;/span&gt;state; ContinueProcessing(state))              &lt;/pre&gt;

&lt;p&gt;Which generates the following message every second:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;I'm still waiting for a message in state 2, come on ... 
      &lt;br /&gt;I'm still waiting for a message in state 2, come on .…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first parameter to &lt;em&gt;SetTimeoutHandler&lt;/em&gt; is how long to wait before triggering the handler. The second parameter is the handler that gets called whenever no message is received for that amount of time. Notice that the handler takes the current state of the agent and returns &lt;em&gt;ContinueProcessing(state)&lt;/em&gt;.&amp;#160; This tells the agent to continue processing messages and sets the current state to &lt;em&gt;state&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The following code:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- 2&lt;/pre&gt;

&lt;p&gt;Then generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;I'm still waiting for a message in state 4, come on ... 
      &lt;br /&gt;I'm still waiting for a message in state 4, come on ...&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;ContinueProcessing&lt;/em&gt; is just one of the three possible values of the (terribly named) &lt;em&gt;AfterError&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;AfterError =
| ContinueProcessing &lt;span style="color: blue"&gt;of &lt;/span&gt;obj
| StopProcessing
| RestartProcessing&lt;/pre&gt;

&lt;p&gt;Let’s see what RestartProcessing does.&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler 1000  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Restart from state %A&amp;quot; &lt;/span&gt;state&lt;br /&gt;                                                                        ; RestartProcessing)&lt;/pre&gt;

&lt;p&gt;Which, as expected, generates a nice stream of:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Restart from state 0 
      &lt;br /&gt;Restart from state 0&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To bring things back to normal (aka no timeout) you can just pass –1 as in:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler -1  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;ContinueProcessing(state))&lt;/pre&gt;

&lt;p&gt;Also, you can stop the agent when a timeout occurs by returning the aptly named &lt;em&gt;StopProcessing&lt;/em&gt;:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetTimeoutHandler 1000  (&lt;span style="color: blue"&gt;fun &lt;/span&gt;state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;Restart from state %A&amp;quot; &lt;/span&gt;state; &lt;br /&gt;                                                                             StopProcessing)&lt;/pre&gt;
Another interesting thing you might want to do is hot swapping of code. More on that in the next part … 

&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649246" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part IV – Custom error management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx</link><pubDate>Fri, 19 Jun 2009 21:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649197</guid><dc:creator>lucabol</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649197.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649197</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt;&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Custom error management&lt;/h4&gt;  &lt;p&gt;In the last part we saw what happens by default in the framework when an error occurs. But that might not be what you want. You might want to have your sophisticated error detection and recovery distributed algorithm.&lt;/p&gt;  &lt;p&gt;To make such a thing possible each agent has a manager. The manager is an agent that gets called whenever an error occurs in the agent it is monitoring.&lt;/p&gt;  &lt;p&gt;In code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;manager = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;(agent, name:string, ex:Exception, msg:obj,&lt;br /&gt;                 state, initialState) &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s restarting ...&amp;quot; &lt;/span&gt;name; agent &amp;lt;-- Restart)
counter1 &amp;lt;-- SetManager(manager)&lt;/pre&gt;

&lt;p&gt;Whenever an error is generated the manager receives a tuple of:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;(agent, name, exception, message, currentState, inititialState)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This manager prints out something and then restarts the agent. Let’s trigger an error by posting the wrong message:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;afdaf&amp;quot;
&lt;/span&gt;counter1 &amp;lt;-- 2&lt;/pre&gt;

&lt;p&gt;The expectation is that the counter will restart from 0 whenever an error is triggered. This is what happens:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Bob restarting ... 
      &lt;br /&gt;From 0 to 2&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which is what we expected. Obviously this is not a very sophisticated error recovery algorithm. You might want to do something more meaningful. Hopefully you have enough information to build whatever you need.&lt;/p&gt;

&lt;p&gt;A particularly important class of unexpected event is timeouts. We’ll talk about them next. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649197" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent: an agent framework in F# – Part III – Default error management</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx</link><pubDate>Fri, 12 Jun 2009 21:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649127</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649127.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649127</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Default error management&lt;/h4&gt;  &lt;p&gt;What happens when an error occurs? Well, ideally you want to notify someone and continue processing messages. By default you want to print the error and as much information as you can about it.&lt;/p&gt;  &lt;p&gt;Let’s first see what happens if you pass the wrong message type:&lt;/p&gt;  &lt;pre class="code"&gt;counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;fst&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;/span&gt;Generates:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent Undefined at state 3 with message &amp;quot;fst&amp;quot;. The agent was started with state 0. 
      &lt;br /&gt;System.InvalidCastException: Specified cast is not valid. 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You get information about the current state of the agent, the message that generated the error, the initial state of the agent and the exception that was generated. But, in a system with several agents, you’d like to know which one agent failed. Then you need to name your agent:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- SetName(&lt;span style="color: maroon"&gt;&amp;quot;Bob&amp;quot;&lt;/span&gt;)
counter1 &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;fadfad&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Now you get (important part in blue):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent &lt;font color="#0000ff"&gt;Bob&lt;/font&gt; at state 3 with message &amp;quot;fadfad&amp;quot;. The agent was started with state 0. 

      &lt;br /&gt;System.InvalidCastException: Specified cast is not valid. 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicFunctions.UnboxGeneric[T](Object source) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important thing is that the agent continues running. It lives to fight another day. Hence:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- 3&lt;/pre&gt;

&lt;p&gt;Produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 3 to 6&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which shows that the agent is running and that it has kept its current state. Also errors can occur inside the message handler with a similar result:&lt;/p&gt;

&lt;pre class="code"&gt;(spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;state / msg) 100) &amp;lt;-- 0&lt;/pre&gt;

&lt;p&gt;Produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&amp;gt; The exception below occurred on agent Undefined at state 100 with message 0. The agent was started with state 100. 
      &lt;br /&gt;System.DivideByZeroException: Attempted to divide by zero. 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0013.it@48-3.Invoke(Int32 msg, Int32 state) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.f@158.Invoke(Object a, Object b) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Core.FastFunc`2.InvokeFast[V](FastFunc`2 func, T arg1, TResult arg2) 

      &lt;br /&gt;&amp;#160;&amp;#160; at FSI_0003.AgentSystem.loop@20-3.Invoke(Unit unitVar) 

      &lt;br /&gt;&amp;#160;&amp;#160; at Microsoft.FSharp.Control.AsyncBuilderImpl.callA@245.Invoke(AsyncParams`1 args)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this might not be what you want. You might want to customize what happens when an error occurs. We’ll talk about that next.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649127" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent : an agent framework in F# – Part II – Agents and control messages</title><link>http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx</link><pubDate>Fri, 05 Jun 2009 21:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9649041</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9649041.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9649041</wfw:commentRss><description>&lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Agents&lt;/h4&gt;  &lt;p&gt;Agents are entities that process messages and keep state between one message and the next. As such they need to be initialized with a lambda that takes a message and a state and returns a new state. In F# pseudo code: msg –&amp;gt; state –&amp;gt; newState. For example the following:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter = spawnAgent (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;state + msg) 0&lt;/pre&gt;

&lt;p&gt;This is a counter that starts from 0 and gets incremented by the value of the received message. Let’s make it print something when it receives a message:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;counter1 = spawnAgent&lt;br /&gt;                (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg state &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;From %i to %i&amp;quot; &lt;/span&gt;state (state + msg); state + msg) 0
counter1 &amp;lt;-- 3 
counter1 &amp;lt;-- 4&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 3 
      &lt;br /&gt;From 3 to 7&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is no &lt;em&gt;spawnParallelAgent&lt;/em&gt;, because I couldn’t figure out its usage patterns. Maybe I don’t have enough creativity. Obviously &lt;em&gt;msg&lt;/em&gt; and &lt;em&gt;state&lt;/em&gt; could be of whatever type (in real application they end up being tuples more often than not).&lt;/p&gt;

&lt;h4&gt;Control messages&lt;/h4&gt;

&lt;p&gt;You can do things to agents. I’m always adding to them but at this stage they are:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;type &lt;/span&gt;Command =
| Restart
| Stop
| SetManager &lt;span style="color: blue"&gt;of &lt;/span&gt;AsyncAgent
| SetName &lt;span style="color: blue"&gt;of &lt;/span&gt;string&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Plus some others. I’ll describe most of them later on, right now I want to talk about &lt;em&gt;Restart&lt;/em&gt; and &lt;em&gt;Stop&lt;/em&gt;. You use the former like this:&lt;/p&gt;

&lt;pre class="code"&gt;counter1 &amp;lt;-- Restart
counter1 &amp;lt;-- 3&lt;/pre&gt;

&lt;p&gt;Which produces:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;From 0 to 3&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This should be somehow surprising to you. You would have thought that you could just post integers to a counter. This is not the case. You can post whatever object. This is useful because it allows to have a common model for passing all sort of messages, it allows for the agent not to be parameterized by the type of the message (and of state) so that you can store them in data structures and allows advanced scenarios (i.e. hot swapping of code).&lt;/p&gt;

&lt;p&gt;This is a debatable decision. I tried to get the best of strongly typing and dynamic typing, while keeping simplicity of usage. The implementation of this is kind of a mess though. We’ll get there.&lt;/p&gt;

&lt;p&gt;BTW: you use Stop just by posting Stop, which stops the agent (forever).&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9649041" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>LAgent : an agent framework in F# – Part I – Workers and ParallelWorkers</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx</link><pubDate>Fri, 29 May 2009 20:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9648937</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9648937.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9648937</wfw:commentRss><description>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Download framework &lt;a href="http://code.msdn.microsoft.com/LAgent"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;All posts are here:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/05/29/lagent-an-agent-framework-in-f-part-i-workers-and-parallelworkers.aspx"&gt;Part I - Workers and ParallelWorkers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/05/lagent-an-agent-framework-in-f-part-ii-agents-and-control-messages.aspx"&gt;Part II - Agents and control messages&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/12/lagent-an-agent-framework-in-f-part-iii-default-error-management.aspx"&gt;Part III - Default error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/19/lagent-an-agent-framework-in-f-part-iv-custom-error-management.aspx"&gt;Part IV - Custom error management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/06/26/lagent-an-agent-framework-in-f-part-v-timeout-management.aspx"&gt;Part V - Timeout management&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/03/lagent-an-agent-framework-in-f-part-vi-hot-swapping-of-code-and-something-silly.aspx"&gt;Part VI - Hot swapping of code&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/07/10/lagent-an-agent-framework-in-f-part-vii-an-auction-application.aspx"&gt;Part VII - An auction framework&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/04/lagent-an-agent-framework-in-f-part-viii-implementing-mapreduce-user-model.aspx"&gt;Part VIII – Implementing MapReduce (user model)&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/lucabol/archive/2009/09/18/lagent-an-agent-framework-in-f-part-ix-counting-words.aspx"&gt;Part IX – Counting words …&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;ul&gt;&lt;/ul&gt;  &lt;h4&gt;Introduction&lt;/h4&gt;  &lt;p&gt;I like to try out different programming paradigms. I started out as an object oriented programmer. In university, I used Prolog. I then learned functional programming. I also experimented with various shared memory parallel paradigms (i.e. async, tasks and such). I now want to learn more about message based parallel programming (&lt;a href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X" mce_href="http://www.amazon.com/Programming-Erlang-Software-Concurrent-World/dp/193435600X"&gt;Erlang&lt;/a&gt; style). I’m convinced that doing so makes me a better programmer. Plus, I enjoy it …&lt;/p&gt;  &lt;p&gt;My usual learning style is to build a framework that replicates a particular programming model and then write code using it. In essence, I build a very constrained environment. For example, when learning functional programming, I didn’t use any OO construct for a while even if my programming language supports them.&lt;/p&gt;  &lt;p&gt;In this case, I built myself a little agent framework based on F# &lt;em&gt;MailboxProcessors&lt;/em&gt;. I could have used &lt;em&gt;MailboxProcessors&lt;/em&gt; directly, but they are too flexible for my goal. Even to write a simple one of these guys, you need to use async and recursion in a specific pattern, which I always forget. Also, there are multiple ways to to do Post. I wanted things to be as simple as possible. I was willing to sacrifice flexibility for that.&lt;/p&gt;  &lt;p&gt;Notice that there are serious efforts in this space (as &lt;a href="http://blogs.msdn.com/maestroteam/" mce_href="http://blogs.msdn.com/maestroteam/"&gt;Axum&lt;/a&gt;). This is not one of them. It’s just a simple thing I enjoy working on between one meeting and the next.&lt;/p&gt;  &lt;h4&gt;Workers and ParallelWorkers&lt;/h4&gt;  &lt;p&gt;The two major primitives are spawning an agent and posting a message.&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;echo = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s&amp;quot; &lt;/span&gt;msg)
echo &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello guys!&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;There are two kinds of agents in my system. A &lt;em&gt;worker&lt;/em&gt; is an agent that doesn’t keep any state between consecutive messages. It is a stateless guy. Notice that the lambda that you pass to create the agent is strongly typed (aka &lt;em&gt;msg&lt;/em&gt; is of type &lt;em&gt;string&lt;/em&gt;). Also notice that I overloaded the &lt;em&gt;&amp;lt;—&lt;/em&gt; operator to mean &lt;em&gt;Post&lt;/em&gt;.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;Given that a worker is stateless, you can create a whole bunch of them and, when a message is posted, route it to one of them transparently.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;parallelEcho = spawnParallelWorker(&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;printfn &lt;span style="color: maroon"&gt;&amp;quot;%s&amp;quot; &lt;/span&gt;s) 10
parallelEcho &amp;lt;-- &lt;span style="color: maroon"&gt;&amp;quot;Hello guys!”&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;For example, in the above code, 10 workers are created and, when a message is posted, it gets routed to one of them (using a super duper innovative dispatching algorithm I’ll describe in the implementation part). This &lt;em&gt;parallelWorker&lt;/em&gt; guy is not really needed, you could easily built it out of the other primitives, but it is kind of cute.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: maroon"&gt;&lt;font color="#000000"&gt;To show the difference between a worker and a &lt;em&gt;parallelWorker&lt;/em&gt;, consider this:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;let &lt;/span&gt;tprint s = printfn &lt;span style="color: maroon"&gt;&amp;quot;%s running on thread %i&amp;quot; &lt;/span&gt;s Thread.CurrentThread.ManagedThreadId
&lt;span style="color: blue"&gt;let &lt;/span&gt;echo1 = spawnWorker (&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint s)
&lt;span style="color: blue"&gt;let &lt;/span&gt;parallelEcho1 = spawnParallelWorker(&lt;span style="color: blue"&gt;fun &lt;/span&gt;s &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;tprint s) 10

&lt;span style="color: blue"&gt;let &lt;/span&gt;messages = [&lt;span style="color: maroon"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;c&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;e&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;f&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;g&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;h&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;i&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;l&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;m&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;n&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;o&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;p&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;q&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;r&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;s&amp;quot;&lt;/span&gt;;&lt;span style="color: maroon"&gt;&amp;quot;t&amp;quot;&lt;/span&gt;]
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;echo1 &amp;lt;-- msg)
messages |&amp;gt; Seq.iter (&lt;span style="color: blue"&gt;fun &lt;/span&gt;msg &lt;span style="color: blue"&gt;-&amp;gt; &lt;/span&gt;parallelEcho1 &amp;lt;-- msg)&lt;/pre&gt;

&lt;p mce_keep="true"&gt;&amp;#160;&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The result of the &lt;em&gt;echo1&lt;/em&gt; iteration is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;a running on thread 11 
      &lt;br /&gt;b running on thread 11 

      &lt;br /&gt;c running on thread 11 

      &lt;br /&gt;d running on thread 11 

      &lt;br /&gt;…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While the result of the &lt;em&gt;parallelEcho1&lt;/em&gt; iteration is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;a running on thread 13 
      &lt;br /&gt;c running on thread 14 

      &lt;br /&gt;b running on thread 12 

      &lt;br /&gt;o running on thread 14 

      &lt;br /&gt;m running on thread 13 

      &lt;br /&gt;…&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice how the latter executes on multiple threads (but not in order). Next time I’ll talk about agents, control messages and error management.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9648937" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>Luke talks about F# on Channel9</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/27/luke-talks-about-f-on-channel9.aspx</link><pubDate>Wed, 27 May 2009 19:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9635464</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9635464.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9635464</wfw:commentRss><description>&lt;p&gt;Here you go: &lt;a title="http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/" href="http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/"&gt;http://channel9.msdn.com/posts/Charles/Luke-Hoban-Latest-version-of-F-Released-Whats-the-story-Whats-next/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9635464" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>A version of the AsyncCache found its way into the Parallel Programming samples …</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/21/a-version-of-the-asynccache-found-its-way-into-the-parallel-programming-samples.aspx</link><pubDate>Thu, 21 May 2009 20:28:13 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9634050</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9634050.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9634050</wfw:commentRss><description>&lt;p&gt;Go &lt;a href="http://code.msdn.microsoft.com/ParExtSamples"&gt;here&lt;/a&gt; to download them. It is in \ParallelExtensionsExtras\CoordinationDataStructures. It has a slightly different design in that it returns Tasks. I’m trying to get &lt;a href="http://blogs.msdn.com/pfxteam"&gt;Stephen&lt;/a&gt; to blog about it so that you can compare them.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9634050" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>I talk about C# and VB Co-Evolution on Channel9 (and some F# …)</title><link>http://blogs.msdn.com/lucabol/archive/2009/05/14/i-talk-about-c-and-vb-co-evolution-on-channel9-and-some-f.aspx</link><pubDate>Thu, 14 May 2009 20:26:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9616619</guid><dc:creator>lucabol</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9616619.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9616619</wfw:commentRss><description>&lt;p&gt;The title says it all. If you are interested, go &lt;a href="http://channel9.msdn.com/posts/Charles/Luca-Bolognese-C-and-VBNET-Co-Evolution-The-Twain-Shall-Meet/#Page=2"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9616619" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/VB/default.aspx">VB</category></item><item><title>Luca at NDC in Oslo 17 – 19 June 2009</title><link>http://blogs.msdn.com/lucabol/archive/2009/03/24/luca-at-ndc-in-oslo-17-19-june-2009.aspx</link><pubDate>Tue, 24 Mar 2009 19:46:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9504664</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9504664.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9504664</wfw:commentRss><description>&lt;p&gt;I’ll be speaking about the future of C# and F#. Oslo brings back so many memories …&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LucaatNDCinOslo1719June2009_8952/Logo%20NDC%202009_2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Logo NDC 2009" border="0" alt="Logo NDC 2009" src="http://blogs.msdn.com/blogfiles/lucabol/WindowsLiveWriter/LucaatNDCinOslo1719June2009_8952/Logo%20NDC%202009_thumb.jpg" width="244" height="72" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;“one of the world’s most important conferences for IT developers and leaders”&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9504664" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/C_2300_+Programming/default.aspx">C# Programming</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category></item><item><title>Bayesian inference in F# – Part IIb – Finding Maia underlying attitude</title><link>http://blogs.msdn.com/lucabol/archive/2009/01/19/bayesian-inference-in-f-part-iib-finding-maia-underlying-attitude.aspx</link><pubDate>Mon, 19 Jan 2009 19:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9340323</guid><dc:creator>lucabol</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/lucabol/comments/9340323.aspx</comments><wfw:commentRss>http://blogs.msdn.com/lucabol/commentrss.aspx?PostID=9340323</wfw:commentRss><description>&lt;P&gt;Other parts:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2008/11/07/bayesian-inference-in-f-part-i-background.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2008/11/07/bayesian-inference-in-f-part-i-background.aspx"&gt;Part I – Background&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/lucabol/archive/2008/11/26/bayesian-inference-in-f-part-iia-a-simple-example-modeling-maia.aspx" mce_href="http://blogs.msdn.com/lucabol/archive/2008/11/26/bayesian-inference-in-f-part-iia-a-simple-example-modeling-maia.aspx"&gt;Part II – A simple example – modeling Maia&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The previous post ended on this note.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;MaiaJointProb attitude action =
    &lt;SPAN style="COLOR: blue"&gt;match &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;with
    &lt;/SPAN&gt;| Happy     &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;happyActions |&amp;gt; List.assoc action
    | UnHappy   &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;unHappyActions |&amp;gt; List.assoc action
    | Quiet     &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;quietActions |&amp;gt; List.assoc action&lt;/PRE&gt;
&lt;P&gt;This is just a two by two matrix. It simply represents which probability is associated to an (attitude, action) tuple. It is useful to think about it in these terms, because it makes easier to grasp the following function:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;/// Conditional probability of a mental state, given a particular observed action
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;MaiaLikelihood action = &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;MaiaJointProb attitude action&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;This is simply a row in the matrix. It answers the question: given that I observe a particular action, what is the probability that Maia has a certain attitude?. This is called “likelihood function” in statistics. Its general form is: given that a I observe an outcome, what is the probability that it is generated by a process with a particular parameter?&lt;/P&gt;
&lt;P&gt;A related question is then: what if I observe a sequence of independent actions? What is the probability that the baby has a certain attitude then? This is answered by the following:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;/// Multiple applications of the previous conditional probabilities for a series of actions (multiplied)
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;MaiaLikelihoods actions =
    &lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;composeLikelihoods previousLikelihood action  = &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;previousLikelihood attitude * MaiaLikelihood action attitude        
    actions |&amp;gt; Seq.fold composeLikelihoods (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;1.)&lt;/PRE&gt;
&lt;P&gt;It is a trivial extension of the previous function (really), once you know that to combine likelihoods you multiply them.&lt;/P&gt;
&lt;P&gt;We now need to describe what our prior is. A prior is our preconceived notion about a particular parameter (in this case the baby’s attitude). You might be tempted to express that notion with a single value, but that would be inaccurate. You need to indicate how confident you are about it. In statistics you do that by choosing a distribution for your belief. This is one of the beauties of Bayesian statistics, everything is a probability distribution. In this case, we really don’t have any previous belief, so we pick the uniform distribution.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;MaiaUniformPrior attitude = 1. / 3.&lt;/PRE&gt;
&lt;P&gt;Think of this as: you haven’t read any baby-attitude-specific study or received any external information about the likely attitude of Maia, so you cannot prefer one attitude over another.&lt;/P&gt;
&lt;P&gt;We are almost done. Now we have to apply the Bayesian theorem and get the un-normalized posterior distribution. Forget about the un-normalized word. What is a posterior distribution? This is your output, your return value. It says: given my prior belief on the value of a parameter and given the outcomes that I observed, this is what I now believe the parameter to be. In this case it goes like: I had no opinion on Maia’s attitude to start with, but after I observed her behavior for a while, I now think she is Happy with probability X, UnHappy with probability Y and Quiet with probability Z.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;/// Calculates the unNormalized posterior given prior and likelihood
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;unNormalizedPosterior (prior:'a &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;float) likelihood =
    &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;theta &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;prior theta * likelihood theta&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;We then need to normalize this thing (it doesn’t sum to one). The way to do it is to divide each probability by the sum of the probabilities for all the possible outcomes.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;/// All possible values for the unobservable parameter (mental state)
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;support = [Happy; UnHappy; Quiet]

&lt;SPAN style="COLOR: green"&gt;/// Normalize the posterior (it integrates to 1.)
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;posterior prior likelihood =
    &lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;post = unNormalizedPosterior prior likelihood
    &lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;sum = support |&amp;gt; List.sum_by (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;post attitude)
    &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;attitude &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;post attitude / sum&lt;/PRE&gt;
&lt;P&gt;We are done. Now we can now start modeling scenarios. Let’s say that you observe [Smile;Smile;Cry;Smile;LookSilly]. What could the underlying attitude of Maia be?&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;maiaIsANormalBaby = posterior MaiaUniformPrior (MaiaLikelihoods [Smile;Smile;Cry;Smile;LookSilly])&lt;/PRE&gt;
&lt;P&gt;We can then execute our little model:&lt;/P&gt;&lt;PRE class=code&gt;maiaIsANormalBaby Happy
maiaIsANormalBaby UnHappy
maiaIsANormalBaby Quiet&lt;/PRE&gt;
&lt;P&gt;And we get (0.5625, 0.0625, 0.375). So Maia is likely to be happy and unlikely to be unhappy. Let’s now model one extreme case:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;/// Extreme cases
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;maiaIsLikelyHappyDist = posterior MaiaUniformPrior (MaiaLikelihoods [Smile;Smile;Smile;Smile;Smile;Smile;Smile])

maiaIsLikelyHappyDist Happy
maiaIsLikelyHappyDist UnHappy&lt;BR&gt;maiaIsLikelyHappyDist Quiet&lt;/PRE&gt;
&lt;P&gt;And we get (0.944, 0.000431, 0.05). Now Maia is almost certainly Happy. Notice that I can confidently make this affirmation because my end result is exactly what I was looking for when I started my quest. Using classical statistics, that wouldn’t be the case.&lt;/P&gt;
&lt;P&gt;A related question I might want to ask is: given the posterior distribution for attitude that I just found, what is the probability of observing a particular action? In other words, given the model that I built, what does it predict?&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;posteriorPredictive jointProb posterior =
    &lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;composeProbs previousProbs attitude = &lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;action &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;previousProbs action + jointProb attitude action * posterior attitude  
    support |&amp;gt; Seq.fold composeProbs (&lt;SPAN style="COLOR: blue"&gt;fun &lt;/SPAN&gt;action &lt;SPAN style="COLOR: blue"&gt;-&amp;gt; &lt;/SPAN&gt;0.)
    
&lt;SPAN style="COLOR: blue"&gt;let &lt;/SPAN&gt;nextLikelyUnknownActionDist = posteriorPredictive MaiaJointProb maiaIsLikelyHappyDist&lt;/PRE&gt;
&lt;P&gt;I don’t have the strength right now to explain the mathematical underpinning of this. In words, this says: considering that Maia can have one of the possible three Attitudes with the probability calculated above, what is the probability that I observe a particular action? Notice that the signature for it is: (Action –&amp;gt; float), which is the compiler way to say it.&lt;/P&gt;
&lt;P&gt;Now we can run the thing.&lt;/P&gt;&lt;PRE class=code&gt;nextLikelyUnknownActionDist Smile
nextLikelyUnknownActionDist Cry
nextLikelyUnknownActionDist LookSilly&lt;/PRE&gt;
&lt;P&gt;And we get (0.588, 0.2056, 0.2055). Why is that? We’ll talk about it in the next post.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9340323" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/lucabol/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://blogs.msdn.com/lucabol/archive/tags/Statistics/default.aspx">Statistics</category></item></channel></rss>