<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;A0EGSHw-eyp7ImA9WhRaE0U.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425</id><updated>2012-02-16T10:53:49.253Z</updated><category term="Rx" /><category term="Windows Phone 7" /><category term="Twitter" /><category term="DGML" /><category term="Prism" /><category term="OData" /><category term="VS2010" /><category term="F# 3.0" /><category term="Project Euler" /><category term="F#" /><category term="T4" /><category term="Type Provider" /><category term="Silverlight" /><category term="MIX" /><title>Round the Campfire</title><subtitle type="html">An exploration of new technologies for software development on the Microsoft platform, both from Microsoft and elsewhere</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.roundthecampfire.net/" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/RoundTheCampfire" /><feedburner:info uri="roundthecampfire" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DEUHRXg4cSp7ImA9WhdbF00.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-8987802641919759924</id><published>2011-10-15T20:17:00.000+01:00</published><updated>2011-10-15T20:17:14.639+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-15T20:17:14.639+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Prism" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Creating composable UI with F# and Prism</title><content type="html">&lt;p&gt;I’ve seen a lot of great demos recently of F# being used to create UI for WPF, Silverlight and Windows Phone. In all cases, this has been a very lightweight UI developed for one specific purpose. This is certainly a valid way to develop user interfaces – no need to overcomplicate, but I wondered if there is also a place for a more “grown up” solution, suitable for building complex applications from the ground up, using F#.&lt;/p&gt;&lt;p&gt;I have recently created a number of full blown user interfaces in C# using &lt;a href="http://compositewpf.codeplex.com/"&gt;Microsoft Patterns &amp;amp; Practices Prism library&lt;/a&gt;. This library provides the building blocks for building maintainable yet complex user interfaces for WPF, Silverlight, Windows Phone. This is typically achieved through a central “shell” application, and a number of loosely coupled modules which contain parts of the user interface and other services. &lt;/p&gt;&lt;p&gt;I am going to attempt to write an F# silverlight application using Prism. This series will describe that process, but won’t necessarily go into detail about how Prism applications themselves work. I would highly recommend that anyone new to Prism watch &lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2009/10/27/prism-and-silverlight-screencasts-on-channel-9.aspx"&gt;Mike Taulty’s excellent series of videos&lt;/a&gt; on this subject, and then refer to the &lt;a href="http://msdn.microsoft.com/en-us/library/gg406140.aspx"&gt;MSDN Developer’s Guide to Microsoft Prism&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Step 1 – Create the Shell Application&lt;/h4&gt;&lt;p&gt;The first step will be to create the basic shell application, without any content. This will be a silverlight application, using F#, so ensure you download &lt;a href="http://go.microsoft.com/fwlink/?LinkId=177428" target="_blank"&gt;Microsoft Silverlight 4 Tools for Visual Studio 2010&lt;/a&gt;. I also installed the &lt;a href="https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=fssliverlightaapp&amp;amp;ReleaseId=4383" target="_blank"&gt;F# Silverlight Application Template&lt;/a&gt; so that I could create the initial silverlight application easily.&lt;/p&gt;&lt;p&gt;With the above installed, I created a silverlight app project named &lt;font size="2" face="Courier New"&gt;FSharpPrismShell &lt;/font&gt;and a Web application project, named Web.Host as a very basic host for this single silverlight app.&lt;/p&gt;&lt;p&gt;When I tested this basic setup, I discovered that the web application project, whilst allowing me to add my silverlight application in the “Silverlight Applications” tab of project properties, didn’t actually copy this over to &lt;font size="2" face="Courier New"&gt;ClientBin &lt;/font&gt;for some unknown reason. Instead, I just added a manual copy to the pre-build events:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;xcopy /Y /R $(SolutionDir)FSharpPrismShell\Bin\Debug\FSharpPrismShell.xap $(ProjectDir)ClientBin&lt;/pre&gt;&lt;p&gt;This allowed me to launch my empty silverlight application correctly in the browser.&lt;/p&gt;&lt;h4&gt;Step 2 – Make the Shell Application a Prism Shell&lt;/h4&gt;&lt;p&gt;Now we need to add Prism to the silverlight application project. I will do this using NuGet. If you don’t have NuGet yet, you should download and install this (in VS2010 use &lt;font size="2" face="Courier New"&gt;Tools –&amp;gt; Extension manager&lt;/font&gt;, then search for and install &lt;font size="2" face="Courier New"&gt;NuGet Package Manager&lt;/font&gt;).&lt;/p&gt;&lt;p&gt;From the Silverlight application project, right click and select &lt;font size="2" face="Courier New"&gt;Manage NuGet Packages&lt;/font&gt;:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/--0G4c3BwS30/TpnE_cD6szI/AAAAAAAAAGk/OY8Cc57sPa8/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-NmcRgTebEnY/TpnFAwXYx-I/AAAAAAAAAGs/zxTDH0DPzOk/image_thumb%25255B1%25255D.png?imgmax=800" width="683" height="383" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Search the online packages for &lt;font size="2" face="Courier New"&gt;Prism&lt;/font&gt;. This should give the above list, so select and install &lt;font size="2" face="Courier New"&gt;Prism &lt;/font&gt;and &lt;font size="2" face="Courier New"&gt;Prism.UnityExtensions &lt;/font&gt;using this.&lt;/p&gt;&lt;p&gt;The contruction of all the elements required in a Prism application is managed by a Bootstrapper. I now need to change my application initialisation to create and run this Bootstrapper, which in turn will create and initialise the shell view (ie the root silverlight control).&lt;/p&gt;&lt;p&gt;So, I’ll firstly modify the default &lt;font size="2" face="Courier New"&gt;Page.xaml&lt;/font&gt;/&lt;font size="2" face="Courier New"&gt;MainPage&lt;/font&gt; combination to create &lt;font size="2" face="Courier New"&gt;Shell.xaml &lt;/font&gt;and &lt;font size="2" face="Courier New"&gt;Shell.fs&lt;/font&gt;.&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot; Background=&amp;quot;Red&amp;quot;&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;TextBlock HorizontalAlignment=&amp;quot;Center&amp;quot; VerticalAlignment=&amp;quot;Bottom&amp;quot;&amp;gt;The red area is from the Shell&amp;lt;/TextBlock&amp;gt;
&amp;lt;/Grid&amp;gt;
&lt;/pre&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;namespace FSharpPrismShell
open System
open System.Windows 
open System.Windows.Controls

type Shell() as this =
&amp;#160;&amp;#160;&amp;#160; inherit UserControl()
&amp;#160;&amp;#160;&amp;#160; do
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Application.LoadComponent(this, new System.Uri(&amp;quot;/FSharpPrismShell;component/Shell.xaml&amp;quot;, System.UriKind.Relative))
&amp;#160;&amp;#160;&amp;#160; let layoutRoot : Grid = downcast this.FindName(&amp;quot;LayoutRoot&amp;quot;)

&amp;#160;&amp;#160;&amp;#160; do 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ()&lt;/pre&gt;&lt;p&gt;Note that I have made the background red, and added the textbox to allow us to later see what belongs to the shell, and what belongs to the plug-in module. Next I’ll create the bootstrapper &lt;font size="2" face="Courier New"&gt;PrismBootStrapper.fs&lt;/font&gt;:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;namespace FSharpPrismShell
open System
open System.Windows 
open System.Windows.Controls
open Microsoft.Practices.Prism.UnityExtensions
open Microsoft.Practices.Prism.Modularity

type PrismBootStrapper() =
&amp;#160;&amp;#160;&amp;#160; inherit UnityBootstrapper()

&amp;#160;&amp;#160;&amp;#160; override this.InitializeShell() =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; base.InitializeShell()
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Application.Current.RootVisual &amp;lt;- downcast this.Shell
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ()

&amp;#160;&amp;#160;&amp;#160; override this.CreateShell() =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; new Shell() :&amp;gt; DependencyObject&lt;/pre&gt;&lt;p&gt;Finally I need to modify &lt;font size="2" face="Courier New"&gt;Program.fs&lt;/font&gt; to initialise and run this bootstrapper, rather than creating the shell directly itself:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let startup () =
&amp;#160;&amp;#160;&amp;#160; let bootStrapper = new PrismBootStrapper()&amp;#160;&amp;#160;&amp;#160;&amp;#160; 
&amp;#160;&amp;#160;&amp;#160; bootStrapper.Run()
&lt;/pre&gt;&lt;p&gt;I can now build and run this application. Note: I’m observing another weird issue – I seem to need to rebuild all before running each time, otherwise the browser launches with the previous version. Not sure if this is an issue with cassini or a problem with the pre-build steps.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-zdf2fxYvDbM/TpnKNVB7glI/AAAAAAAAAG0/1yTfcNt5Wz4/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-UCBkSWQDYyk/TpnKNnQnSOI/AAAAAAAAAG8/6UBF2IhzA4Y/image_thumb%25255B3%25255D.png?imgmax=800" width="495" height="211" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Therefore, I have a working Prism shell application. The next step is to create a plug-in module for this, and wire the two halves together, so that the plug-in appears within this shell.&lt;/p&gt;&lt;h4&gt;Step 3 – Create the Basic Plug-in Module&lt;/h4&gt;&lt;p&gt;The most basic plug-in for Prism is a module which exposes a single view to be composed within the shell. This is what we will implement today. Create a second silverlight application project and name this one &lt;font size="2" face="Courier New"&gt;FSharpPrismModule&lt;/font&gt;.&lt;/p&gt;&lt;p&gt;Refactor the default &lt;font size="2" face="Courier New"&gt;Page.xaml&lt;/font&gt;/&lt;font size="2" face="Courier New"&gt;MainPage&lt;/font&gt; combination into &lt;font size="2" face="Courier New"&gt;MainView.xaml&lt;/font&gt; and &lt;font size="2" face="Courier New"&gt;MainView.fs&lt;/font&gt;:&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot; Background=&amp;quot;Green&amp;quot;&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;TextBlock HorizontalAlignment=&amp;quot;Center&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot; FontSize=&amp;quot;36&amp;quot;&amp;gt;Hello, Modular UI&amp;lt;/TextBlock&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;TextBlock HorizontalAlignment=&amp;quot;Center&amp;quot; VerticalAlignment=&amp;quot;Bottom&amp;quot;&amp;gt;The green area is from the Module&amp;lt;/TextBlock&amp;gt;
&amp;lt;/Grid&amp;gt;
&lt;/pre&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;type MainView() as this =
&amp;#160;&amp;#160;&amp;#160; inherit UserControl()
&amp;#160;&amp;#160;&amp;#160; do
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Application.LoadComponent(this, new System.Uri(&amp;quot;/FSharpPrismModule;component/MainView.xaml&amp;quot;, System.UriKind.Relative))
&amp;#160;&amp;#160;&amp;#160; let layoutRoot : Grid = downcast this.FindName(&amp;quot;LayoutRoot&amp;quot;)

&amp;#160;&amp;#160;&amp;#160; do 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ()&lt;/pre&gt;&lt;p&gt;Now create the discoverable type which implements &lt;font size="2" face="Courier New"&gt;IModule &lt;/font&gt;– this is the core of a Prism module, and will be used to register this module with the shell application later. We’ll call this &lt;font size="2" face="Courier New"&gt;ModuleDef.fs&lt;/font&gt;:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;type ModuleDef(regionManager: IRegionManager) =

&amp;#160;&amp;#160;&amp;#160; interface IModule with
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; member this.Initialize() =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; regionManager.RegisterViewWithRegion(&amp;quot;ShellContent&amp;quot;, typeof&amp;lt;MainView&amp;gt;) 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; ignore&lt;/pre&gt;&lt;p&gt;What we do here is register a view which Prism will automatically use for any regions defined in the shell named “&lt;font size="2" face="Courier New"&gt;ShellContent&lt;/font&gt;”. Also note that the constructor parameter of type &lt;font size="2" face="Courier New"&gt;IRegionManager &lt;/font&gt;is automatically generated by Prism/Unity when the module is loaded. This is true of any interfaces registered with unity, and is the standard method for providing core services to loaded modules.&lt;/p&gt;&lt;p&gt;This will build and run fine, but we won’t yet see the module for two reasons – it hasn’t been registered with Prism, and we haven’t defined a region in the shell into which its UI should be placed.&lt;/p&gt;&lt;h4&gt;Step 4 – Register the Module with the Shell&lt;/h4&gt;&lt;p&gt;Firstly we need to update Shell.xaml to add a control which will act as the placeholder, into which Prism will inject the view from our module:&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;...
xmlns:Regions=&amp;quot;http://www.codeplex.com/prism&amp;quot;
...

&amp;lt;Grid x:Name=&amp;quot;LayoutRoot&amp;quot; Background=&amp;quot;Red&amp;quot;&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;ContentControl Margin=&amp;quot;20,20&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; HorizontalAlignment=&amp;quot;Stretch&amp;quot; VerticalAlignment=&amp;quot;Stretch&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; HorizontalContentAlignment=&amp;quot;Stretch&amp;quot; VerticalContentAlignment=&amp;quot;Stretch&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Regions:RegionManager.RegionName=&amp;quot;ShellContent&amp;quot; /&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;TextBlock HorizontalAlignment=&amp;quot;Center&amp;quot; VerticalAlignment=&amp;quot;Bottom&amp;quot;&amp;gt;The red area is from the Shell&amp;lt;/TextBlock&amp;gt;
&amp;lt;/Grid&amp;gt;
&lt;/pre&gt;&lt;p&gt;Now we need to create a module catalog, which is a xaml file defining the list of modules which Prism should make available as plug-ins. Note that this can also be achieved programmatically within the bootstrapper. We’ll create a file called &lt;font size="2" face="Courier New"&gt;modules.xaml&lt;/font&gt; and include this as content within the shell project.&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Modularity:ModuleCatalog 
&amp;#160;&amp;#160;&amp;#160; xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
&amp;#160;&amp;#160;&amp;#160; xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
&amp;#160;&amp;#160;&amp;#160; xmlns:sys=&amp;quot;clr-namespace:System;assembly=mscorlib&amp;quot;
&amp;#160;&amp;#160;&amp;#160; xmlns:Modularity=&amp;quot;clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism&amp;quot;&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;Modularity:ModuleInfo
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Ref=&amp;quot;FSharpPrismModule.xap&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ModuleName=&amp;quot;FSharpPrismModule&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ModuleType=&amp;quot;FSharpPrismModule.ModuleDef, FSharpPrismModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null&amp;quot;&amp;gt;
&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Modularity:ModuleInfo&amp;gt;
&amp;lt;/Modularity:ModuleCatalog &amp;gt;&lt;/pre&gt;&lt;p&gt;Note that we are actually including the &lt;font size="2" face="Courier New"&gt;FSharpPrismModule &lt;/font&gt;xap file here, and specifying the type to be loaded within this xap file. Prism works out all the complexity of one xap file (the shell) including another xap file (the module) on our behalf.&lt;/p&gt;&lt;p&gt;In order for this to be found, I will need to update the prebuild step to xcopy this new xap file into the &lt;font size="2" face="Courier New"&gt;ClientBin &lt;/font&gt; directory&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;xcopy /Y /R $(SolutionDir)FSharpPrismModule\Bin\Debug\FSharpPrismModule.xap $(ProjectDir)ClientBin&lt;br /&gt;xcopy /Y /R $(SolutionDir)FSharpPrismShell\Bin\Debug\FSharpPrismShell.xap $(ProjectDir)ClientBin&lt;/pre&gt;&lt;p&gt;This said, I was initially banging my head against a wall when the runtime continued to fail to load &lt;font size="2" face="Courier New"&gt;FSharpPrismModule.ModuleDef&lt;/font&gt;. Eventually (with help from .NET Reflector) I realised that the generated module had the version number 0.0.0.0, so I added an &lt;font size="2" face="Courier New"&gt;AssemblyInfo.fs &lt;/font&gt;file to the module project:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;open System.Reflection
open System.Runtime.CompilerServices
open System.Runtime.InteropServices

// The following GUID is for the ID of the typelib if this project is exposed to COM
[&amp;lt;assembly: Guid(&amp;quot;06725367-D5EE-4D48-BC6B-827211C133A6&amp;quot;)&amp;gt;]
[&amp;lt;assembly: AssemblyVersion(&amp;quot;1.0.0.0&amp;quot;)&amp;gt;]
[&amp;lt;assembly: AssemblyFileVersion(&amp;quot;1.0.0.0&amp;quot;)&amp;gt;]

() &lt;/pre&gt;&lt;p&gt;In order for the module itself to be loaded, we need to ensure that the bootstrapper knows how to find the modules. In order to achieve this, I added another override to PrismBootStrapper.fs:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;override this.CreateModuleCatalog() =
&amp;#160;&amp;#160;&amp;#160; let catalog = ModuleCatalog.CreateFromXaml(new Uri(&amp;quot;modules.xaml&amp;quot;, UriKind.Relative))
&amp;#160;&amp;#160;&amp;#160; catalog :&amp;gt; IModuleCatalog
&lt;/pre&gt;&lt;p&gt;So finally, Prism can find our module, load it, and determine that it can provide a view for the placeholder control within our shell. If we now run this application, the result will be:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-cdX8K0sh6vg/TpnZxwLZORI/AAAAAAAAAHE/8fTk6rcLpPE/s1600-h/image%25255B11%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-vtnqJg0T4ks/TpnZyE8uiDI/AAAAAAAAAHM/yzCq7gpBFD4/image_thumb%25255B5%25255D.png?imgmax=800" width="492" height="207" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;That’s enough Prism for now. What we have is a very simple composed user interface written entirely in F#. It isn’t very useful yet, as we only have one module, we don’t have any additional services, or communication between the shell and the module or between modules. I’ll endeavour to expand this into something more useful in the near future, but for the moment this is a reasonable start.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Source code is &lt;strong&gt;available for &lt;/strong&gt;&lt;/em&gt;&lt;a href="https://bitbucket.org/_chrisballard/fsharpprism/overview" target="_blank"&gt;&lt;em&gt;&lt;strong&gt;download&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;&lt;em&gt; from bitbucket. &lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-8987802641919759924?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/LjXNv_qlxzQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/8987802641919759924/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=8987802641919759924" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/8987802641919759924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/8987802641919759924?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/LjXNv_qlxzQ/creating-composable-ui-with-f-and-prism.html" title="Creating composable UI with F# and Prism" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-NmcRgTebEnY/TpnFAwXYx-I/AAAAAAAAAGs/zxTDH0DPzOk/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2011/10/creating-composable-ui-with-f-and-prism.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4GQng7fyp7ImA9WhdVE0k.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-1588467346226871189</id><published>2011-09-18T12:22:00.000+01:00</published><updated>2011-09-18T12:22:03.607+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-18T12:22:03.607+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="F# 3.0" /><category scheme="http://www.blogger.com/atom/ns#" term="Type Provider" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title>Creating a no-thrills custom type provider in F# 3.0 – some progress</title><content type="html">&lt;p&gt;I thought I would come at this from a different angle today. Following on from comments on the previous post, I decided it would make sense to try and find out what F#/Visual Studio does when I add a reference to my type provider.&lt;/p&gt;&lt;p&gt;So I have added a separate solution &lt;font size="2" face="Courier New"&gt;TypeProviderConsumer &lt;/font&gt;and opened that in another instance of VS 11. I create an empty F# console app project, and then go back to my type provider solution. Having corrected the omission that Ramon mentioned in a comment on my previous post, my type provider now looks like this:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false"&gt;using System;
using System.Reflection;
using Microsoft.FSharp.Core;
using Microsoft.FSharp.Core.CompilerServices;
&amp;#160;&amp;#160;&amp;#160; 
[Serializable, TypeProvider, CompilationMapping(SourceConstructFlags.ObjectType)]
public class BasicTypeProvider : ITypeProvider, IProvidedNamespace, IDisposable
{
&amp;#160;&amp;#160;&amp;#160; Type baseType;

&amp;#160;&amp;#160;&amp;#160; public BasicTypeProvider(TypeProviderConfig config)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; baseType = typeof(StaticType);
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type ApplyStaticArguments(Type typeWithoutArguments, string typeNameWithArguments, object[] staticArguments)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return baseType;
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public System.Linq.Expressions.Expression GetInvokerExpression(System.Reflection.MethodBase syntheticMethodBase, System.Linq.Expressions.ParameterExpression[] parameters)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public IProvidedNamespace[] GetNamespaces()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new IProvidedNamespace[] { (IProvidedNamespace) this };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public System.Reflection.ParameterInfo[] GetStaticParameters(Type typeWithoutArguments)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new ParameterInfo[] { };&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public event EventHandler Invalidate;

&amp;#160;&amp;#160;&amp;#160; public void Dispose()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public IProvidedNamespace[] GetNestedNamespaces()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new IProvidedNamespace[] { };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type[] GetTypes()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new Type[] { baseType };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public string NamespaceName
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return &amp;quot;TestTypeProvider&amp;quot;; }
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type ResolveTypeName(string typeName)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (string.Equals(typeName, &amp;quot;StaticType&amp;quot;))
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.baseType;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;
&amp;#160;&amp;#160;&amp;#160; }
}
&lt;/pre&gt;&lt;p&gt;I set breakpoints in every method and property above, then choose &lt;font size="2" face="Courier New"&gt;Debug&lt;/font&gt;, &lt;font size="2" face="Courier New"&gt;Attach to Process &lt;/font&gt;and attach to the other instance of Visual Studio:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-UBhtJzJ4nvs/TnXTZZC8gKI/AAAAAAAAAGM/V1bxK9zQknc/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-xs6KNPdU1Sg/TnXTZ8AvK5I/AAAAAAAAAGQ/AABXboMFM5c/image_thumb%25255B1%25255D.png?imgmax=800" width="540" height="83" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Switching back to the other instance, I add a reference to my custom type provider, and bam, we hit the first breakpoint. Awesome. Progress.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-GzkX45tPsl0/TnXTaFaJecI/AAAAAAAAAGU/_3_WxOLbmss/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-mJQ9piEibYI/TnXTagXcZCI/AAAAAAAAAGY/nVNuhKCRggw/image_thumb%25255B3%25255D.png?imgmax=800" width="498" height="92" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Checking out what config gets passed into our constructor:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-KznrhRcvq-E/TnXTbQov7XI/AAAAAAAAAGc/FeDd6sqhAVQ/s1600-h/image%25255B15%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-HvARJ3DLHk4/TnXTcACh-cI/AAAAAAAAAGg/v3m9HWA_2IA/image_thumb%25255B9%25255D.png?imgmax=800" width="846" height="96" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If I keep hitting &lt;font size="2" face="Courier New"&gt;F5&lt;/font&gt;, it hits the breakpoints in this order:&lt;/p&gt;&lt;font size="2" face="Courier New"&gt;&lt;ol&gt;&lt;li&gt;GetNamespaces()&lt;/li&gt;
&lt;li&gt;NamespaceName { get; }&lt;/li&gt;
&lt;li&gt;GetTypes()&lt;/li&gt;
&lt;li&gt;GetNestedNamespaces()&lt;/li&gt;&lt;/ol&gt;&lt;/font&gt;&lt;p&gt;Then it repeats once more, starting at the constructor. &lt;/p&gt;&lt;p&gt;This is all good news – it means that I’m not missing some strange attribute or other construct. My type provider is being initialised and queried, so I guess at the moment I get the “&lt;font size="2" face="Courier New"&gt;This is not a provided type&lt;/font&gt;” message because I’m not implementing some or all of &lt;font size="2" face="Courier New"&gt;ITypeProvider &lt;/font&gt;or &lt;font size="2" face="Courier New"&gt;IProvidedNamespace &lt;/font&gt;correctly. This is something I can work on by getting my head back into &lt;font size="2" face="Courier New"&gt;FSharp.Data.TypeProviders&lt;/font&gt;. Watch this space.&lt;/p&gt;&lt;p&gt;As an aside – notice the &lt;font size="2" face="Courier New"&gt;TemporaryFolder &lt;/font&gt;property in the config above. If I take a look into the location to which it points, I find a number of generated dlls for the past few days. It turns out these are generated by the Linq to SQL type provider (which I have been testing alongside this investigation) in pairs – one for the type that I generate in my F# code (&lt;font size="2" face="Courier New"&gt;dbSchema&lt;/font&gt;) and another which contains the actual &lt;font size="2" face="Courier New"&gt;DataContext &lt;/font&gt;class and classes for each table in my database. This is good – I understand some more about what is generated under the hood for type providers, and should help me with the next stage of the investigation.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-1588467346226871189?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/WDKS_KLsaDY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/1588467346226871189/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=1588467346226871189" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1588467346226871189?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1588467346226871189?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/WDKS_KLsaDY/creating-no-thrills-custom-type_18.html" title="Creating a no-thrills custom type provider in F# 3.0 – some progress" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-xs6KNPdU1Sg/TnXTZ8AvK5I/AAAAAAAAAGQ/AABXboMFM5c/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2011/09/creating-no-thrills-custom-type_18.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ACSH48cCp7ImA9WhdVEkw.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-1049972315658954778</id><published>2011-09-17T00:29:00.000+01:00</published><updated>2011-09-17T00:29:29.078+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-17T00:29:29.078+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="F# 3.0" /><category scheme="http://www.blogger.com/atom/ns#" term="Type Provider" /><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title>Creating a no-thrills custom type provider in F# 3.0 – attempt 1</title><content type="html">&lt;p&gt;F# 3.0 was released this week at the Microsoft Build conference as part of the Visual Studio 11 Developer Preview. Full details are available on &lt;a href="http://blogs.msdn.com/b/fsharpteam/archive/2011/09/14/f-3-0-developer-preview-now-available.aspx"&gt;the F# team blog&lt;/a&gt; – I recommend you read through this and have a play with the new features – it’s a really feature packed release.&lt;/p&gt;&lt;p&gt;I’m interested specifically in Type Providers, which are a new direction in F#, and provide some of the power of dynamic languages (types generated on the fly to wrap some form of structured data, such as XML from an OData service) but without the performance issues or late binding that come with these. Type Providers are actually an extensibility mechanism for the compiler, which allow for the compiler to query the type provider assembly, which does exactly that – provides types on the fly, which both the compiler and VS Intellisense can make use of. This all happens at compile time, and therefore whilst the code has features with a dynamic flavour, the result remains statically typed.&lt;/p&gt;&lt;p&gt;What I want to do is to create the simplest possible example of a custom type provider. Essentially I would like to create one which provides only one type, and that itself is just a static type within the type provider assembly, no Emit code this time around.&lt;/p&gt;&lt;h3&gt;FSharp.Data.TypeProviders&lt;/h3&gt;&lt;p&gt;There doesn’t appear to be much (any?) information available yet concerning custom type providers, so my first port of call is to crack open the key F# type providers assembly – &lt;font size="2" face="Courier New"&gt;FSharp.Data.TypeProviders.dll &lt;/font&gt;using Reflector, and see what I can find.&lt;/p&gt;&lt;p&gt;The key touch point appears to be in &lt;font size="2" face="Courier New"&gt;Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders -&lt;/font&gt;&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false"&gt;[Serializable, TypeProvider, CompilationMapping(SourceConstructFlags.ObjectType)]
public class DataProviders : ITypeProvider, IProvidedNamespace, IDisposable
{
// ...
}
&lt;/pre&gt;&lt;p&gt;And the key interface here, defined in &lt;font size="2" face="Courier New"&gt;Microsoft.FSharp.Core.CompilerServices &lt;/font&gt;is:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;public interface ITypeProvider : IDisposable
{
&amp;#160;&amp;#160;&amp;#160; // Events
&amp;#160;&amp;#160;&amp;#160; [CLIEvent]
&amp;#160;&amp;#160;&amp;#160; event EventHandler Invalidate;

&amp;#160;&amp;#160;&amp;#160; // Methods
&amp;#160;&amp;#160;&amp;#160; Type ApplyStaticArguments(Type typeWithoutArguments, string typeNameWithArguments, object[] staticArguments);
&amp;#160;&amp;#160;&amp;#160; Expression GetInvokerExpression(MethodBase syntheticMethodBase, ParameterExpression[] parameters);
&amp;#160;&amp;#160;&amp;#160; IProvidedNamespace[] GetNamespaces();
&amp;#160;&amp;#160;&amp;#160; ParameterInfo[] GetStaticParameters(Type typeWithoutArguments);
}
&lt;/pre&gt;&lt;p&gt;So I should be able to create an assembly (in C# to start off with) containing a class of my own which implements this above interface, and that should give me a type provider, right?&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false"&gt;using System;
using System.Reflection;
using Microsoft.FSharp.Core;
using Microsoft.FSharp.Core.CompilerServices;
&amp;#160;&amp;#160;&amp;#160; 
[Serializable, TypeProvider, CompilationMapping(SourceConstructFlags.ObjectType)]
public class BasicTypeProvider : ITypeProvider, IProvidedNamespace, IDisposable
{
&amp;#160;&amp;#160;&amp;#160; Type baseType;

&amp;#160;&amp;#160;&amp;#160; public BasicTypeProvider()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; baseType = typeof(StaticType);
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type ApplyStaticArguments(Type typeWithoutArguments, string typeNameWithArguments, object[] staticArguments)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return baseType;
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public System.Linq.Expressions.Expression GetInvokerExpression(System.Reflection.MethodBase syntheticMethodBase, System.Linq.Expressions.ParameterExpression[] parameters)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public IProvidedNamespace[] GetNamespaces()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new IProvidedNamespace[] { (IProvidedNamespace) this };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public System.Reflection.ParameterInfo[] GetStaticParameters(Type typeWithoutArguments)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new ParameterInfo[] { };&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public event EventHandler Invalidate;

&amp;#160;&amp;#160;&amp;#160; public void Dispose()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public IProvidedNamespace[] GetNestedNamespaces()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new IProvidedNamespace[] { };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type[] GetTypes()
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return new Type[] { baseType };
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public string NamespaceName
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return &amp;quot;RegistryTypeProvider&amp;quot;; }
&amp;#160;&amp;#160;&amp;#160; }

&amp;#160;&amp;#160;&amp;#160; public Type ResolveTypeName(string typeName)
&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (string.Equals(typeName, &amp;quot;StaticType&amp;quot;))
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return this.baseType;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return null;
&amp;#160;&amp;#160;&amp;#160; }
}
&lt;/pre&gt;&lt;p&gt;Note that I have included the same attributes as used in the &lt;font size="2" face="Courier New"&gt;FSharp.Data.TypeProviders &lt;/font&gt;assembly, as I assume they’re important, and in all the implementations I just shunt around the &lt;font size="2" face="Courier New"&gt;StaticType &lt;/font&gt;type (which is just a POCO class with a couple of properties, for demo purposes). I don’t know how to handle &lt;font size="2" face="Courier New"&gt;GetInvokerExpression &lt;/font&gt;at the moment, so I’ll return null here, and just hope I get away with it.&lt;/p&gt;&lt;p&gt;Now I build this assembly, and then create a new F# console application project to act as the consumer of this type provider. Add a reference to the type provider assembly and then create a simple use in &lt;font size="2" face="Courier New"&gt;Program.fs &lt;/font&gt;-&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;open TestTypeProvider

[&amp;lt;Generate&amp;gt;]
type myType = TestTypeProvider.BasicTypeProvider&lt;/pre&gt;&lt;p&gt;Sadly this doesn’t work. I get red squigglies under &lt;font size="2" face="Courier New"&gt;TestTypeProvider.BasicTypeProvider &lt;/font&gt;and the message &lt;font size="2" face="Courier New"&gt;&lt;strong&gt;“This is not a provided type. Consider removing the 'Generate' attribute from this type definition.”&lt;/strong&gt;&lt;/font&gt; Thanks. Actually I’d prefer to have a working type provider, if you don’t mind.&lt;/p&gt;&lt;p&gt;If I look back at FSharp.Data.TypeProviders.dll I can see an assembly level attribute which might be important: &lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false"&gt;... 
[assembly: TypeProviderAssembly]
...&lt;/pre&gt;&lt;p&gt;So I add that to my type provider project, rebuild (and looks like I need to remove the type provider assembly reference from my consumer project, and then restart visual studio in order to avoid problems with the type provider assembly being locked).&lt;/p&gt;&lt;p&gt;Nope. &lt;font size="2" face="Courier New"&gt;&lt;strong&gt;“This is not a provided type. Consider removing the 'Generate' attribute from this type definition.”&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;I’ve now tried many tweaks to the attributes and restarted VS many times but no luck getting around this error message. I think I will take a look at this again in the morning, and dig around inside Reflector to see what else I can discover.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-1049972315658954778?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/N_H4lMCvppY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/1049972315658954778/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=1049972315658954778" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1049972315658954778?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1049972315658954778?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/N_H4lMCvppY/creating-no-thrills-custom-type.html" title="Creating a no-thrills custom type provider in F# 3.0 – attempt 1" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2011/09/creating-no-thrills-custom-type.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkADSHsyfCp7ImA9WxFUFks.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-7063059268417013512</id><published>2010-06-27T19:52:00.000+01:00</published><updated>2010-06-27T19:52:59.594+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-27T19:52:59.594+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="Project Euler" /><title>Prime Numbers - Building the EulerMaths library in F#</title><content type="html">&lt;p&gt;Those of you who are doing &lt;a href="http://projecteuler.net/" target="_blank"&gt;Project Euler&lt;/a&gt; know what I am talking about by the &lt;font size="2" face="Courier New"&gt;EulerMaths&lt;/font&gt; library. There are certain fundamentals which crop up again and again in the questions and it is important to work these into a reusable and performant library.&lt;/p&gt;&lt;p&gt;The first and most obvious of these is the Prime Number generator. Many questions rely on generating a sequence of primes, or on determining whether or not an individual number is a prime. In this post I will step through a number of potential solutions, starting from the most naive, and going to my current state of the art.&lt;/p&gt;&lt;h3&gt;Generating a Sequence of Primes - the Naive Solution&lt;/h3&gt;&lt;p&gt;The algorithm for this solution is simple. Starting with what we know to be the lowest prime (2), count up to the highest number we want to test (which we call hp) , for each candidate we then test whether or not it is a prime. Lets look at that latter part first:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let isPrime n =
&amp;#160;&amp;#160;&amp;#160; let rec testAllDivisors d =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if n = d then true
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if n%d = 0 then false
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else testAllDivisors (d+1)
&amp;#160;&amp;#160;&amp;#160; testAllDivisors 2&lt;/pre&gt;&lt;p&gt;This is a very common recursive pattern, we have an outer function with the simple parameter - &lt;font size="2" face="Courier New"&gt;n&lt;/font&gt; - the number to test, then define a recursive function with local scope. This recursive function steps through all possible divisors of &lt;font size="2" face="Courier New"&gt;n&lt;/font&gt;, starting from 2. If we find a divisor on the way, the number is not prime, if we reach &lt;font size="2" face="Courier New"&gt;n&lt;/font&gt;, then the number must be prime.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note that the inner function uses tail recursion - the very last statement is the recursive call, and it performs no calculations with the result. This means the compiler can optimise out stack usage by removing the return address of each successive call to &lt;font size="2" face="Courier New"&gt;testAllDivisors&lt;/font&gt;, which effectively means the last call will return directly to &lt;font size="2" face="Courier New"&gt;isPrime&lt;/font&gt;, not to each of the previous execution of &lt;font size="2" face="Courier New"&gt;testAllDivisors&lt;/font&gt;. This means we can recurse as deep as we need, and will never see a &lt;font size="2" face="Courier New"&gt;StackOverflowException&lt;/font&gt;.&lt;/em&gt; &lt;/p&gt;&lt;p&gt;We can test performance of this routine with successively larger primes, and with timed mode on in F# Interactive (use the &lt;font size="2" face="Courier New"&gt;#time&lt;/font&gt;&lt;font size="2" face="Courier New"&gt;;;&lt;/font&gt; command to enable).&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;&lt;u&gt;Digits&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="133"&gt;&lt;u&gt;Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="133"&gt;&lt;u&gt;Time (ms)&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;5&lt;/td&gt;

&lt;td valign="top" width="133"&gt;50069&lt;/td&gt;

&lt;td valign="top" width="133"&gt;0&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;6&lt;/td&gt;

&lt;td valign="top" width="133"&gt;509203&lt;/td&gt;

&lt;td valign="top" width="133"&gt;2&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;7&lt;/td&gt;

&lt;td valign="top" width="133"&gt;5048423&lt;/td&gt;

&lt;td valign="top" width="133"&gt;23&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;8&lt;/td&gt;

&lt;td valign="top" width="133"&gt;50943779&lt;/td&gt;

&lt;td valign="top" width="133"&gt;295&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;9&lt;/td&gt;

&lt;td valign="top" width="133"&gt;506977979&lt;/td&gt;

&lt;td valign="top" width="133"&gt;2440&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="133"&gt;10&lt;/td&gt;

&lt;td valign="top" width="133"&gt;2147483647&lt;/td&gt;

&lt;td valign="top" width="133"&gt;9863&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;So with primes up to 7 digits or so, the performance isn't too bad for one off tests, but you can see that if we were building a sequence of primes from this, the performance would degrade exponentially. Lets try this now.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let allPrimesUpTo hp =
&amp;#160;&amp;#160;&amp;#160; let rec testEachPrime n = seq {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if n &amp;lt;= hp then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if isPrime n then yield n
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! testEachPrime (n+1)
&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160; testEachPrime 2&lt;/pre&gt;&lt;p&gt;So this function makes use of our prime test to obtain a sequence of primes up to a given maximum. This uses the recursive sequence generation pattern of &lt;font size="2" face="Courier New"&gt;yield&lt;/font&gt; followed by &lt;font size="2" face="Courier New"&gt;yield!&lt;/font&gt; and the tail recursive call, which is a really nice way of building sequences. When testing the timing of this, don't forget that F# interactive will only iterate over the first 4 elements of the sequence, so you need to ensure that the entire sequence is enumerated when testing out the times. I used something like:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;allPrimesUpTo 100000 |&amp;gt; Seq.length&lt;/pre&gt;&lt;p&gt;Which forces enumeration of the entire sequence. So lets try that now, using a steadily increasing maximum:&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="551"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="190"&gt;&lt;u&gt;Max&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="172"&gt;&lt;u&gt;Highest Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="187"&gt;&lt;u&gt;Time (ms)&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="190"&gt;1000&lt;/td&gt;

&lt;td valign="top" width="172"&gt;997&lt;/td&gt;

&lt;td valign="top" width="187"&gt;2&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="190"&gt;10000&lt;/td&gt;

&lt;td valign="top" width="172"&gt;9973&lt;/td&gt;

&lt;td valign="top" width="187"&gt;30&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="190"&gt;100000&lt;/td&gt;

&lt;td valign="top" width="172"&gt;99991&lt;/td&gt;

&lt;td valign="top" width="187"&gt;2808&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="190"&gt;500000&lt;/td&gt;

&lt;td valign="top" width="172"&gt;499979&lt;/td&gt;

&lt;td valign="top" width="187"&gt;52644&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="190"&gt;1000000&lt;/td&gt;

&lt;td valign="top" width="193"&gt;999983&lt;/td&gt;

&lt;td valign="top" width="229"&gt;187455&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;What did I tell you! So this is acceptable for generating sequences of the lower primes, but becomes unusable very quickly. As many Euler problems are designed to weed out poorly optimised algorithms, you won't get very far with this implementation.&lt;/p&gt;&lt;h3&gt;Going Parallel&lt;/h3&gt;&lt;p&gt;The next option we have is to keep the same brute force approach, but to identify a means to partition the calculations and run in parallel. If we firstly change &lt;font size="2" face="Courier New"&gt;testEachPrime&lt;/font&gt; to support a subrange of the overall range, and yield a sequence within this range:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let rec testEachPrime (f,t) = seq {
&amp;#160;&amp;#160;&amp;#160; if f &amp;lt;= t then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (isPrime f) then yield f
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! testEachPrime ((f+1),t)
}
&lt;/pre&gt;&lt;p&gt;What we also need to do it partition an overall range, of say &lt;font size="2" face="Courier New"&gt;2 .. 100000&lt;/font&gt; into a set of subranges which can be used for each parallel task. I make a few assumptions here, the main one being that the overall range will be many times larger than the number of tasks we will run, so an uncomplicated implementation will suffice:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let divideWork f t nd =
&amp;#160;&amp;#160;&amp;#160; let range = (t+1) - f
&amp;#160;&amp;#160;&amp;#160; if range &amp;lt; nd then failwith &amp;quot;Range is less than the number of divisions&amp;quot;
&amp;#160;&amp;#160;&amp;#160; let delta = range/nd
&amp;#160;&amp;#160;&amp;#160; [| 0 .. nd-1 |] |&amp;gt; Array.map (fun i -&amp;gt; let ti = ((i+1)*delta)-1
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ((i*delta)+f),(if i &amp;gt;= (nd-1) then t else ti+f))&lt;/pre&gt;&lt;p&gt;This takes the overall range &lt;font size="2" face="Courier New"&gt;f..t&lt;/font&gt; and number of required divisions, returning an array of tuples representing the &lt;font size="2" face="Courier New"&gt;f..t&lt;/font&gt; of each subdivision. Because the division isn't going to be perfect every time, the last pair will be truncated to ensure that its last value will always be the given &lt;font size="2" face="Courier New"&gt;t&lt;/font&gt;. So trying out our example from above we get:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; divideWork 2 100000 16;;
val it : (int * int) [] =
[|(2, 6250); (6251, 12499); (12500, 18748); (18749, 24997); (24998, 31246);
&amp;#160;&amp;#160;&amp;#160; (31247, 37495); (37496, 43744); (43745, 49993); (49994, 56242);
&amp;#160;&amp;#160;&amp;#160; (56243, 62491); (62492, 68740); (68741, 74989); (74990, 81238);
&amp;#160;&amp;#160;&amp;#160; (81239, 87487); (87488, 93736); (93737, 100000)|]&lt;/pre&gt;&lt;p&gt;This is all we need now to divide our work up into subtasks, so piecing it together we get:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let allPrimesUpTo hp =
&amp;#160;&amp;#160;&amp;#160; let getResultsTask (f,t) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let rec testEachPrime (f,t) = seq {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if f &amp;lt;= t then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (isPrime f) then yield f
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! testEachPrime ((f+1),t)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; testEachPrime (f,t) |&amp;gt; Array.ofSeq

&amp;#160;&amp;#160;&amp;#160; let ntasks = System.Environment.ProcessorCount * 16

&amp;#160;&amp;#160;&amp;#160; if hp &amp;lt; (ntasks * 10) then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; getResultsTask (2,hp)
&amp;#160;&amp;#160;&amp;#160; else
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let taskArgs = divideWork 2 hp ntasks

&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let results = 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Async.Parallel [ for taskNo in 0 .. (ntasks-1) -&amp;gt; async { return getResultsTask taskArgs.[taskNo] } ]
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; Async.RunSynchronously
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; results |&amp;gt; Array.concat&lt;/pre&gt;&lt;p&gt;Note first that we package &lt;font size="2" face="Courier New"&gt;testEachPrime&lt;/font&gt; into &lt;font size="2" face="Courier New"&gt;getResultsTask&lt;/font&gt;, which converts the sequence into an array. This is very important, as it ensures that the enumeration (and therefore calculations) are performed whilst running parallel. If you return just a sequence, the &lt;font size="2" face="Courier New"&gt;Async.Parallel&lt;/font&gt; does no work, and it all ends up running sequentially during the final call to &lt;font size="2" face="Courier New"&gt;Array.concat&lt;/font&gt;.&lt;/p&gt;&lt;p&gt;Next, we determine a number of tasks to run based on the CPU (or more specifically the number of cores). I will demonstrate later where the &lt;font size="2" face="Courier New"&gt;*16&lt;/font&gt; comes in. If the prime we are looking for isn't much lower than the number of tasks we will run, we don't bother with the overhead of scheduling to threads, and instead just run the whole thing synchronously.&lt;/p&gt;&lt;p&gt;So finally, if we do want to run in parallel, we get the array of subranges, then setup and run an &lt;font size="2" face="Courier New"&gt;async&lt;/font&gt; workflow for each task, passing in this range as its parameter. This collates the task results into an array of arrays (which luckily is in the same order as our tasks run), which we can then &lt;font size="2" face="Courier New"&gt;concat&lt;/font&gt; into a single array of results. See &lt;a href="http://blogs.msdn.com/b/dsyme/archive/2010/01/09/async-and-parallel-design-patterns-in-f-parallelizing-cpu-and-i-o-computations.aspx" target="_blank"&gt;Don Syme's Blog&lt;/a&gt; for much more detail about how this works.&lt;/p&gt;&lt;h4&gt;Determining how many Tasks to run&lt;/h4&gt;&lt;p&gt;This will depend on each circumstance, and probably also has a lot to do with the individual processor architectures. My main machine has 8 cores (which is what &lt;font size="2" face="Courier New"&gt;System.Environment.ProcessorCount&lt;/font&gt; returns), but if I run with just 8 tasks, the workload doesn't balance out too well:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_bqE0F2FFSYA/TCdv-9_wrKI/AAAAAAAAAD0/FEMMm-Voj68/s1600-h/unbalanced-task-load%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="unbalanced-task-load" border="0" alt="unbalanced-task-load" src="http://lh6.ggpht.com/_bqE0F2FFSYA/TCdv_p8kunI/AAAAAAAAAD4/5k6uLqP6Lyk/unbalanced-task-load_thumb%5B3%5D.png?imgmax=800" width="615" height="137" /&gt;&lt;/a&gt; You can see the falloff isn't sharp, and some cores are clearly done before others. By gradually increasing the number of tasks, we hit a sweet spot at CPUs * 16, which gives us a more balanced looking load, without too much overhead (and we get the quickest overall times at this level).&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_bqE0F2FFSYA/TCdwAM6iUjI/AAAAAAAAAD8/waWIBwg44_o/s1600-h/balanced-task-load%5B5%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="balanced-task-load" border="0" alt="balanced-task-load" src="http://lh3.ggpht.com/_bqE0F2FFSYA/TCdwAivVx9I/AAAAAAAAAEA/CsA_H3nsyxs/balanced-task-load_thumb%5B3%5D.png?imgmax=800" width="610" height="141" /&gt;&lt;/a&gt; This clearly looks much better, with clean ramp up and ramp down on each core. So with this in place, we can repeat our performance test from the previous implementation, and look again at the results, side by side:&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="636"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="119"&gt;&lt;u&gt;Max&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="97"&gt;&lt;u&gt;Highest Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="145"&gt;&lt;u&gt;Time (Naive) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="147"&gt;&lt;u&gt;Time (Parallel, 8 cores) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="126"&gt;&lt;u&gt;Speed up&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="119"&gt;1000&lt;/td&gt;

&lt;td valign="top" width="97"&gt;997&lt;/td&gt;

&lt;td valign="top" width="145"&gt;2&lt;/td&gt;

&lt;td valign="top" width="147"&gt;1&lt;/td&gt;

&lt;td valign="top" width="126"&gt;x2&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="119"&gt;10000&lt;/td&gt;

&lt;td valign="top" width="97"&gt;9973&lt;/td&gt;

&lt;td valign="top" width="145"&gt;30&lt;/td&gt;

&lt;td valign="top" width="147"&gt;7&lt;/td&gt;

&lt;td valign="top" width="125"&gt;x4&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="119"&gt;100000&lt;/td&gt;

&lt;td valign="top" width="97"&gt;99991&lt;/td&gt;

&lt;td valign="top" width="145"&gt;2808&lt;/td&gt;

&lt;td valign="top" width="147"&gt;372&lt;/td&gt;

&lt;td valign="top" width="125"&gt;x7.5&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="119"&gt;500000&lt;/td&gt;

&lt;td valign="top" width="98"&gt;499979&lt;/td&gt;

&lt;td valign="top" width="145"&gt;52644&lt;/td&gt;

&lt;td valign="top" width="147"&gt;6947&lt;/td&gt;

&lt;td valign="top" width="125"&gt;x7.5&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="118"&gt;1000000&lt;/td&gt;

&lt;td valign="top" width="101"&gt;999983&lt;/td&gt;

&lt;td valign="top" width="154"&gt;187455&lt;/td&gt;

&lt;td valign="top" width="160"&gt;26016&lt;/td&gt;

&lt;td valign="top" width="140"&gt;x7.2&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;This is great, more or less exactly the speed up we would expect, as there will always be a certain amount of overhead in spinning up threads, and in the concatenation of results once all tasks complete. However, this is only useful if you happen to have a nice big multi-core box, and clearly once we go beyond 10s of millions, we will be needing a cray if we stick with the brute force method.&lt;/p&gt;&lt;h3&gt;Do it With a Sieve&lt;/h3&gt;&lt;p&gt;There are occasions where the brute force approach is enough. However there is a much more elegant way to generate a sequence of primes, called the Sieve of Eratosthenes - which is explained better than I can, by means of an animated diagram, on &lt;a href="http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes" target="_blank"&gt;the wikipedia entry&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Lets first implement a very functional version of this sieve:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let eratosthenesSieve =
&amp;#160;&amp;#160;&amp;#160; let allNaturalsFrom2 = Seq.initInfinite ((+)1) |&amp;gt; Seq.filter ((&amp;lt;=)2)
&amp;#160;&amp;#160;&amp;#160; let rec sieveNext sq = seq {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let n = sq |&amp;gt; Seq.nth 0
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield n
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let newSq = sq |&amp;gt; Seq.filter (fun i -&amp;gt; i%n &amp;lt;&amp;gt; 0)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! sieveNext newSq
&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160; sieveNext allNaturalsFrom2&lt;/pre&gt;&lt;p&gt;In this implementation we start with an infinite sequence of natural numbers, excluding 1, then pass this into the sieve which yields the first element (which is 2 to start with), and recurses using a new sequence which excludes all members in the originals sequence which are multiples of 2, then does 3, 5, ...&lt;/p&gt;&lt;p&gt;It works great, but look at the times:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; eratosthenesSieve |&amp;gt; Seq.take 100 |&amp;gt; Seq.nth 99;;
Real: 00:00:00.133, CPU: 00:00:00.124, GC gen0: 1, gen1: 0, gen2: 0
val it : int = 541
&amp;gt; eratosthenesSieve |&amp;gt; Seq.take 200 |&amp;gt; Seq.nth 199;;
Real: 00:00:01.782, CPU: 00:00:01.778, GC gen0: 6, gen1: 0, gen2: 0
val it : int = 1223
&amp;gt; eratosthenesSieve |&amp;gt; Seq.take 300 |&amp;gt; Seq.nth 299;;
Real: 00:00:08.443, CPU: 00:00:08.455, GC gen0: 16, gen1: 1, gen2: 0
val it : int = 1987
&amp;gt; eratosthenesSieve |&amp;gt; Seq.take 400 |&amp;gt; Seq.nth 399;;
Real: 00:00:25.824, CPU: 00:00:25.786, GC gen0: 29, gen1: 1, gen2: 0
val it : int = 2741&lt;/pre&gt;&lt;p&gt;This clearly is not going to be much use for us. Perhaps if we make the sequences finite, the results will improve?&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let eratosthenesSieveFinite hp =
&amp;#160;&amp;#160;&amp;#160; let allNaturalsFrom2 = seq [2..hp]
&amp;#160;&amp;#160;&amp;#160; let rec sieveNext sq = seq {
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (sq |&amp;gt; Seq.length) &amp;gt; 0 then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let n = sq |&amp;gt; Seq.nth 0
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield n
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let newSq = sq |&amp;gt; Seq.filter (fun i -&amp;gt; i%n &amp;lt;&amp;gt; 0)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! sieveNext newSq
&amp;#160;&amp;#160;&amp;#160; }
&amp;#160;&amp;#160;&amp;#160; sieveNext allNaturalsFrom2&lt;/pre&gt;&lt;p&gt;Lets try this with the same sizes of sequence (we use the biggest prime returned above to ensure the sequence sizes are the same:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; eratosthenesSieveFinite 541 |&amp;gt; Seq.take 100 |&amp;gt; Seq.nth 99;;
Real: 00:00:00.387, CPU: 00:00:00.390, GC gen0: 4, gen1: 0, gen2: 0
val it : int = 541
&amp;gt; eratosthenesSieveFinite 1223 |&amp;gt; Seq.take 200 |&amp;gt; Seq.nth 199;;
Real: 00:00:05.262, CPU: 00:00:05.382, GC gen0: 22, gen1: 1, gen2: 1
val it : int = 1223
&amp;gt; eratosthenesSieveFinite 1987 |&amp;gt; Seq.take 300 |&amp;gt; Seq.nth 299;;
Real: 00:00:25.003, CPU: 00:00:25.006, GC gen0: 50, gen1: 3, gen2: 0
val it : int = 1987&lt;/pre&gt;&lt;p&gt;Wow, that's MUCH worse. Postulating that dealing with enumerable sequences rather than cold, hard arrays sucks our perf, lets try this same solution, but using arrays instead of sequences. Also, I realise we should stop eliminating once n passes sqrt(hp) so we can add a check for that:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let eratosthenesSieveArrays hp =
&amp;#160;&amp;#160;&amp;#160; let allNaturalsFrom2 = [|2..hp|]
&amp;#160;&amp;#160;&amp;#160; let limit = int(sqrt(float(hp)))
&amp;#160;&amp;#160;&amp;#160; let rec sieveNext sq = [|
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (sq |&amp;gt; Array.length) &amp;gt; 0 then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let n = sq.[0]
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if n &amp;gt; limit then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for n in sq -&amp;gt; n
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield n
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let newSq = sq |&amp;gt; Array.filter (fun i -&amp;gt; i%n &amp;lt;&amp;gt; 0)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; yield! sieveNext newSq
&amp;#160;&amp;#160;&amp;#160; |]
&amp;#160;&amp;#160;&amp;#160; sieveNext allNaturalsFrom2&lt;/pre&gt;&lt;p&gt;Which is a vast improvement. Lets merge the new perf results into our performance grid:&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="634"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="102"&gt;&lt;u&gt;Max&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="101"&gt;&lt;u&gt;Highest Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="144"&gt;&lt;u&gt;Time (Naive) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="152"&gt;&lt;u&gt;Time (Parallel, 8 cores) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="133"&gt;&lt;u&gt;Time (Array Sieve) ms&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="103"&gt;1000&lt;/td&gt;

&lt;td valign="top" width="103"&gt;997&lt;/td&gt;

&lt;td valign="top" width="143"&gt;2&lt;/td&gt;

&lt;td valign="top" width="151"&gt;1&lt;/td&gt;

&lt;td valign="top" width="133"&gt;1&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="104"&gt;10000&lt;/td&gt;

&lt;td valign="top" width="104"&gt;9973&lt;/td&gt;

&lt;td valign="top" width="143"&gt;30&lt;/td&gt;

&lt;td valign="top" width="151"&gt;7&lt;/td&gt;

&lt;td valign="top" width="132"&gt;45&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="104"&gt;100000&lt;/td&gt;

&lt;td valign="top" width="105"&gt;99991&lt;/td&gt;

&lt;td valign="top" width="142"&gt;2808&lt;/td&gt;

&lt;td valign="top" width="150"&gt;372&lt;/td&gt;

&lt;td valign="top" width="133"&gt;176&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="105"&gt;500000&lt;/td&gt;

&lt;td valign="top" width="106"&gt;499979&lt;/td&gt;

&lt;td valign="top" width="142"&gt;52644&lt;/td&gt;

&lt;td valign="top" width="150"&gt;6947&lt;/td&gt;

&lt;td valign="top" width="132"&gt;2164&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="106"&gt;1000000&lt;/td&gt;

&lt;td valign="top" width="106"&gt;999983&lt;/td&gt;

&lt;td valign="top" width="142"&gt;187455&lt;/td&gt;

&lt;td valign="top" width="150"&gt;26016&lt;/td&gt;

&lt;td valign="top" width="132"&gt;2853&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;So now the functional sieve approach is generally faster than even the 8 core parallel approach. One final approach we should try is to go for a slightly more imperative style - create a mutable array containing all potential primes, and then step through the sieve crossing out elements in the array (setting to 0), finally returning a sequence of all non-zero elements from the array.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let eratosthenesSieveImperative hp =
&amp;#160;&amp;#160;&amp;#160; let limit = int(sqrt(float(hp)))
&amp;#160;&amp;#160;&amp;#160; let primes = [| 0 .. hp |]
&amp;#160;&amp;#160;&amp;#160; primes.[1] &amp;lt;- 0
&amp;#160;&amp;#160;&amp;#160; let rec iterate n =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if n &amp;lt; limit then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [2*n .. n .. hp ] |&amp;gt; Seq.iter (fun i -&amp;gt; primes.[i] &amp;lt;- 0)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let n = primes |&amp;gt; Seq.filter ((&amp;lt;)n) |&amp;gt; Seq.nth 0
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; iterate n
&amp;#160;&amp;#160;&amp;#160; iterate 2
&amp;#160;&amp;#160;&amp;#160; primes |&amp;gt; Seq.filter ((&amp;lt;&amp;gt;)0)&lt;/pre&gt;&lt;p&gt;This gives the best results so far:&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="719"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="109"&gt;&lt;u&gt;Max&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="108"&gt;&lt;u&gt;Highest Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="131"&gt;&lt;u&gt;Time (Naive) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="139"&gt;&lt;u&gt;Time (Parallel, 8 cores) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="122"&gt;&lt;u&gt;Time (Array Sieve) ms&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="108"&gt;&lt;u&gt;Time (Imperative Sieve) ms&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="110"&gt;1000&lt;/td&gt;

&lt;td valign="top" width="109"&gt;997&lt;/td&gt;

&lt;td valign="top" width="131"&gt;2&lt;/td&gt;

&lt;td valign="top" width="139"&gt;1&lt;/td&gt;

&lt;td valign="top" width="121"&gt;1&lt;/td&gt;

&lt;td valign="top" width="107"&gt;8&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="111"&gt;10000&lt;/td&gt;

&lt;td valign="top" width="110"&gt;9973&lt;/td&gt;

&lt;td valign="top" width="131"&gt;30&lt;/td&gt;

&lt;td valign="top" width="139"&gt;7&lt;/td&gt;

&lt;td valign="top" width="121"&gt;45&lt;/td&gt;

&lt;td valign="top" width="107"&gt;7&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="111"&gt;100000&lt;/td&gt;

&lt;td valign="top" width="110"&gt;99991&lt;/td&gt;

&lt;td valign="top" width="131"&gt;2808&lt;/td&gt;

&lt;td valign="top" width="139"&gt;372&lt;/td&gt;

&lt;td valign="top" width="121"&gt;176&lt;/td&gt;

&lt;td valign="top" width="107"&gt;54&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="111"&gt;500000&lt;/td&gt;

&lt;td valign="top" width="110"&gt;499979&lt;/td&gt;

&lt;td valign="top" width="131"&gt;52644&lt;/td&gt;

&lt;td valign="top" width="139"&gt;6947&lt;/td&gt;

&lt;td valign="top" width="121"&gt;2164&lt;/td&gt;

&lt;td valign="top" width="107"&gt;267&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="111"&gt;1000000&lt;/td&gt;

&lt;td valign="top" width="110"&gt;999983&lt;/td&gt;

&lt;td valign="top" width="131"&gt;187455&lt;/td&gt;

&lt;td valign="top" width="139"&gt;26016&lt;/td&gt;

&lt;td valign="top" width="121"&gt;2853&lt;/td&gt;

&lt;td valign="top" width="107"&gt;616&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;This goes to show that sometimes you need to sacrifice some of the beauty of functional code to glean that last step in performance. Here we have a mutable array being used for working, but we still follow best practices by not exposing this mutable data to the caller of this function. One thing to bear in mind with this approach though, is that we are creating an in-memory array, so if you go much higher than a few million primes, you will risk running out of memory.&lt;/p&gt;&lt;h3&gt;Parallel isPrime&lt;/h3&gt;&lt;p&gt;Sometimes all we want to do is check a single number for prime, and especially if this number is very large, we don't want to generate a sequence or run out of memory by using a sieve, so lets use our knowledge about parallelising tasks, and create a parallel version of &lt;font size="2" face="Courier New"&gt;isPrime&lt;/font&gt;:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let isPrimeParallel n =
&amp;#160;&amp;#160;&amp;#160; let getResultsTask (f,t) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let rec testAllDivisors (f,t) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if f = t then true
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if n%f = 0 then false
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else testAllDivisors (f+1,t)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; testAllDivisors (f,t)

&amp;#160;&amp;#160;&amp;#160; let ntasks = System.Environment.ProcessorCount * 16

&amp;#160;&amp;#160;&amp;#160; if n &amp;lt; (ntasks * 10) then
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; getResultsTask (2,n)
&amp;#160;&amp;#160;&amp;#160; else
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let taskArgs = divideWork 2 n ntasks

&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let results = 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Async.Parallel [ for taskNo in 0 .. (ntasks-1) -&amp;gt; async { return getResultsTask taskArgs.[taskNo] } ]
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; Async.RunSynchronously
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; not(results |&amp;gt; Seq.exists ((=)false)) &lt;/pre&gt;&lt;p&gt;So the logic here is to divide up the problem space again, and run the prime test logic on subsets, collate the results, and only return true if each subtask returned true (i.e. none of them found a divisor). Lets compare the perf of this with the original.&lt;/p&gt;&lt;table border="0" cellspacing="0" cellpadding="2" width="540"&gt;&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="137"&gt;&lt;u&gt;Digits&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="149"&gt;&lt;u&gt;Prime&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="133"&gt;&lt;u&gt;Original Time (ms)&lt;/u&gt;&lt;/td&gt;

&lt;td valign="top" width="119"&gt;&lt;u&gt;Parallel (ms)&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="137"&gt;5&lt;/td&gt;

&lt;td valign="top" width="150"&gt;50069&lt;/td&gt;

&lt;td valign="top" width="133"&gt;0&lt;/td&gt;

&lt;td valign="top" width="118"&gt;4&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="136"&gt;6&lt;/td&gt;

&lt;td valign="top" width="151"&gt;509203&lt;/td&gt;

&lt;td valign="top" width="132"&gt;2&lt;/td&gt;

&lt;td valign="top" width="118"&gt;1&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="136"&gt;7&lt;/td&gt;

&lt;td valign="top" width="152"&gt;5048423&lt;/td&gt;

&lt;td valign="top" width="132"&gt;23&lt;/td&gt;

&lt;td valign="top" width="118"&gt;3&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="136"&gt;8&lt;/td&gt;

&lt;td valign="top" width="152"&gt;50943779&lt;/td&gt;

&lt;td valign="top" width="132"&gt;295&lt;/td&gt;

&lt;td valign="top" width="118"&gt;45&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="136"&gt;9&lt;/td&gt;

&lt;td valign="top" width="152"&gt;506977979&lt;/td&gt;

&lt;td valign="top" width="132"&gt;2440&lt;/td&gt;

&lt;td valign="top" width="118"&gt;305&lt;/td&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td valign="top" width="136"&gt;10&lt;/td&gt;

&lt;td valign="top" width="152"&gt;2147483647&lt;/td&gt;

&lt;td valign="top" width="132"&gt;9863&lt;/td&gt;

&lt;td valign="top" width="118"&gt;1285&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;&lt;/table&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;I wouldn't suggest you need to do this depth of analysis on all problems, but for very critical parts of your Euler toolset, it is clearly worth digging into the options. There are still optimisations we could do here - for example the parallel &lt;font size="2" face="Courier New"&gt;isPrime&lt;/font&gt; could support cancellation, so that all tasks abort as soon as we find a divisor, as we know then that the number is not a prime.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-7063059268417013512?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/gx-vD72iwZ0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/7063059268417013512/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=7063059268417013512" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/7063059268417013512?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/7063059268417013512?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/gx-vD72iwZ0/prime-numbers-building-eulermaths.html" title="Prime Numbers - Building the EulerMaths library in F#" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_bqE0F2FFSYA/TCdv_p8kunI/AAAAAAAAAD4/5k6uLqP6Lyk/s72-c/unbalanced-task-load_thumb%5B3%5D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/06/prime-numbers-building-eulermaths.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UHRX8zcSp7ImA9WxFUFUg.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-4039275667715824485</id><published>2010-06-26T00:04:00.003+01:00</published><updated>2010-06-26T14:33:54.189+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-26T14:33:54.189+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="F#" /><title>My First F# Post</title><content type="html">&lt;p&gt;I have been experimenting with F# for a couple of years now, occasionally solving problems from &lt;a href="http://www.projecteuler.net/" target="_blank"&gt;Project Euler&lt;/a&gt; but have never got around to posting a blog entry on this subject. Recently I have been lucky enough to spend some time with &lt;a href="http://blogs.msdn.com/b/dsyme/" target="_blank"&gt;Don Syme&lt;/a&gt; and the people of the excellent &lt;a href="http://skillsmatter.com/user-group/open-source-dot-net/london-f-sharp-user-group" target="_blank"&gt;F#unctional Londoners user group&lt;/a&gt;, a number of whom complained that I don't have an F# blog, so I thought I had better put my money where my mouth is and put a post together.&lt;/p&gt;&lt;h3&gt;Getting Started&lt;/h3&gt;&lt;p&gt;F# is a functional programming language based on OCaml which combines the best of both worlds in terms of the pure functional aspects of ML and pragmatic use of imperative / object oriented language features. F# is now a first class member of the .NET languages and is part of Visual Studio 2010. &lt;/p&gt;&lt;p&gt;If you are new to F#, my recommended training list is as follows:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Firstly, get a taster by following &lt;a href="http://channel9.msdn.com/shows/Going+Deep/C9-Lectures-Dr-Don-Syme-Introduction-to-F-1-of-3/" target="_blank"&gt;Don's excellent introductory series&lt;/a&gt; on Channel 9. &lt;/li&gt;
&lt;li&gt;After that, learn what functional programming is all about in &lt;a href="http://www.manning.com/petricek/" target="_blank"&gt;Real World Functional Programming&lt;/a&gt; by Tomas Petricek and Jon Skeet. &lt;/li&gt;
&lt;li&gt;Finally, read &lt;a href="http://apress.com/book/view/1430224312" target="_blank"&gt;Expert F# 2.0&lt;/a&gt; by Don Syme himself, Adam Granicz and Antonio Cisternino which does what it says on the cover. &lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;There are also a number of (proper) blogs on F#, such as Don's (linked above), &lt;a href="http://tomasp.net/blog/" target="_blank"&gt;Tomas Petricek&lt;/a&gt;, &lt;a href="http://strangelights.com/blog/" target="_blank"&gt;Robert Pickering&lt;/a&gt;, &lt;a href="http://lucabolognese.wordpress.com/" target="_blank"&gt;Luca Bolognese&lt;/a&gt; and &lt;a href="http://www.trelford.com/blog/" target="_blank"&gt;Phillip Trelford&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;What's it all About?&lt;/h3&gt;&lt;p&gt;I have already worked through over 50 of the puzzles in Project Euler, most of which I solved using F#. This is a fantastic way to improve both your F# and your maths skills (by the way several people have told me they don't do Project Euler because their F#/maths skills aren't good enough - if you think this, you have got it backwards, you will improve both as you work your way through).&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Regarding Project Euler - if you have come to this post simply to find the solution, then I feel sorry for you, you have missed the point. I would really recommend that you have a good stab at the solution yourself before reading any further. The sense of achievement as you increment that score one by one is strangely addictive, and if you just copy the work of others, you miss out on all of that.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;That said, this post will take you through my solution for &lt;a href="http://projecteuler.net/index.php?section=problems&amp;amp;id=54" target="_blank"&gt;Euler 54&lt;/a&gt;, which (somewhat unusually) isn't a particularly mathematical problem, but turns out to be a great way to demonstrate some of the features of the F# language. The basic principle of this problem is to compare two hands of cards in the game of poker, and to determine which is the winning hand.&lt;/p&gt;&lt;h3&gt;Representing the Cards&lt;/h3&gt;&lt;p&gt;The first step is to come up with a representation for the playing cards themselves, as well as some functions for parsing from a plain text description (which is what the Euler problem provides) and for evaluating individual cards. The representation here uses discriminated unions, and is similar to that shown in chapter 3 of &lt;a href="http://oreilly.com/catalog/9780596153656" target="_blank"&gt;Programming F#&lt;/a&gt; by Chris Smith.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;type Suit =
&amp;#160;&amp;#160;&amp;#160; | Hearts
&amp;#160;&amp;#160;&amp;#160; | Diamonds
&amp;#160;&amp;#160;&amp;#160; | Clubs
&amp;#160;&amp;#160;&amp;#160; | Spades

type Card =
&amp;#160;&amp;#160;&amp;#160; | Ace of Suit
&amp;#160;&amp;#160;&amp;#160; | King of Suit
&amp;#160;&amp;#160;&amp;#160; | Queen of Suit
&amp;#160;&amp;#160;&amp;#160; | Jack of Suit
&amp;#160;&amp;#160;&amp;#160; | Value of int * Suit
&lt;/pre&gt;&lt;p&gt;These two discriminated unions allow us to represent any of the cards found in a deck of playing cards, eg &lt;font size="2" face="Courier New"&gt;Ace(Spades)&lt;/font&gt; or &lt;font size="2" face="Courier New"&gt;Value(2,Hearts)&lt;/font&gt;.&amp;#160; Next we need a function to take the string representation of a card (such as &lt;font size="2" face="Courier New"&gt;&amp;quot;AS&amp;quot;&lt;/font&gt;, &lt;font size="2" face="Courier New"&gt;&amp;quot;2H&amp;quot;&lt;/font&gt;, &lt;font size="2" face="Courier New"&gt;&amp;quot;TC&amp;quot;&lt;/font&gt;) and return a value of the relevant discriminated union.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let parseCard (s:string) =
&amp;#160;&amp;#160;&amp;#160; let parseSuit (c:char) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; match c with
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | 'H' -&amp;gt; Hearts
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | 'D' -&amp;gt; Diamonds
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | 'C' -&amp;gt; Clubs
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | 'S' -&amp;gt; Spades
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | _ -&amp;gt; failwith &amp;quot;Unknown suit&amp;quot;
&amp;#160;&amp;#160;&amp;#160; let charVal (c:char) = int(c)-48
&amp;#160;&amp;#160;&amp;#160; if s.Length &amp;lt;&amp;gt; 2 then failwith &amp;quot;Card should be 2 characters in length&amp;quot;
&amp;#160;&amp;#160;&amp;#160; let suit = parseSuit s.[1]
&amp;#160;&amp;#160;&amp;#160; match s.[0] with
&amp;#160;&amp;#160;&amp;#160; | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' -&amp;gt; Value(charVal(s.[0]),suit)
&amp;#160;&amp;#160;&amp;#160; | 'T' -&amp;gt; Value(10,suit)
&amp;#160;&amp;#160;&amp;#160; | 'J' -&amp;gt; Jack(suit)
&amp;#160;&amp;#160;&amp;#160; | 'Q' -&amp;gt; Queen(suit)
&amp;#160;&amp;#160;&amp;#160; | 'K' -&amp;gt; King(suit)
&amp;#160;&amp;#160;&amp;#160; | 'A' -&amp;gt; Ace(suit)
&amp;#160;&amp;#160;&amp;#160; | _ -&amp;gt; failwith &amp;quot;Unknown rank&amp;quot;
&lt;/pre&gt;&lt;p&gt;Talking through this routine, you can see we have a helper function (which is local in scope to the function itself) called &lt;font size="2" face="Courier New"&gt;parseSuit&lt;/font&gt; which takes a single character and attempts to parse this into a suit by using a pattern matching expression. Within the main body of the routine we ensure that the string is 2 characters, no more, no less, get the suit, and then finally pattern match the rank of the card. For the numeric characters we use the tried and tested technique of subtracting the ASCII value of &lt;font size="2" face="Courier New"&gt;'0'&lt;/font&gt; in order to convert the char into a numeric value.&lt;/p&gt;&lt;p&gt;Playing with these functions in the enormously useful &lt;font size="2" face="Courier New"&gt;F# Interactive &lt;/font&gt;REPL window, we can check they work as expected:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; parseCard &amp;quot;KS&amp;quot;;;
val it : Card = King Spades
&amp;gt; parseCard &amp;quot;3D&amp;quot;;;
val it : Card = Value (3,Diamonds)
&amp;gt; parseCard &amp;quot;ZD&amp;quot;;;
System.Exception: Unknown rank
at FSI_0008.parseCard(String s) in C:\Svn\roundthecampfire\trunk\ProjectEuler\EulerHost\Euler54.fs:line 46
at &amp;lt;StartupCode$FSI_0011&amp;gt;.$FSI_0011.main@()
Stopped due to error&lt;/pre&gt;&lt;p&gt;And to conclude this section, lets create a function to load the two hands (as a tuple) from a single line of 10 cards as per the supplied &lt;font size="2" face="Courier New"&gt;poker.txt&lt;/font&gt; file, and then try that function on a couple of lines from the file.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let parseHands (sl:string) =
&amp;#160;&amp;#160;&amp;#160; let parts = sl.Split(' ')
&amp;#160;&amp;#160;&amp;#160; if parts.Length &amp;lt;&amp;gt; 10 then failwith &amp;quot;Hands must be 10 cards&amp;quot;
&amp;#160;&amp;#160;&amp;#160; else
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let comb = parts |&amp;gt; Array.map parseCard
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (Array.sub comb 0 5 |&amp;gt; List.ofArray),(Array.sub comb 5 5 |&amp;gt; List.ofArray)
&lt;/pre&gt;&lt;p&gt;This is our first use of some of the really cool F# higher order functions, such as &lt;font size="2" face="Courier New"&gt;Array.map&lt;/font&gt; and &lt;font size="2" face="Courier New"&gt;List.ofArray&lt;/font&gt;, as well as the forward pipe &lt;font size="2" face="Courier New"&gt;|&amp;gt;&lt;/font&gt; operator. Essentially this function gets an array of the individual 2 char strings, and projects these using &lt;font size="2" face="Courier New"&gt;Array.map &lt;/font&gt;and &lt;font size="2" face="Courier New"&gt;parseCard &lt;/font&gt;into a set of 10 cards. These cards are then split into two hands of 5 cards using &lt;font size="2" face="Courier New"&gt;Array.sub&lt;/font&gt;.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; parseHands &amp;quot;8C TS KC 9H 4S 7D 2S 5D 3S AC&amp;quot;;;
val it : Card list * Card list =
([Value (8,Clubs); Value (10,Spades); King Clubs; Value (9,Hearts);
&amp;#160;&amp;#160;&amp;#160; Value (4,Spades)],
[Value (7,Diamonds); Value (2,Spades); Value (5,Diamonds); Value (3,Spades);
&amp;#160;&amp;#160;&amp;#160; Ace Clubs])
&amp;gt; parseHands &amp;quot;5C AD 5D AC 9C 7C 5H 8D TD KS&amp;quot;;;
val it : Card list * Card list =
([Value (5,Clubs); Ace Diamonds; Value (5,Diamonds); Ace Clubs;
&amp;#160;&amp;#160;&amp;#160; Value (9,Clubs)],
[Value (7,Clubs); Value (5,Hearts); Value (8,Diamonds); Value (10,Diamonds);
&amp;#160;&amp;#160;&amp;#160; King Spades])&lt;/pre&gt;&lt;h3&gt;Functions to Determine the Rank of a Hand&lt;/h3&gt;&lt;p&gt;Now that we have our hands of cards, we need a way to determine the highest rank to which a hand belongs, and giving us enough data to be able to compare two hands of the same rank, by checking the highest card which is part of the rank (e.g. a two pairs of Ace,Ace and 9,9 is higher than two pairs of King,Kind and 10,10) or highest cards which aren't part of the rank (e.g. pair of Kings with Ace high is better than pair of Kings with Jack high).&lt;/p&gt;&lt;p&gt;Before we do this, we need a function to return the relative value of cards as per 2,3,4,5,6,7,8,9,T,J,Q,K,A and a function which returns just the suit for a given card (so we can check for flushes).&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let valueOf (c:Card) =
&amp;#160;&amp;#160;&amp;#160; match c with
&amp;#160;&amp;#160;&amp;#160; | Ace(_) -&amp;gt; 12
&amp;#160;&amp;#160;&amp;#160; | King(_) -&amp;gt; 11
&amp;#160;&amp;#160;&amp;#160; | Queen(_) -&amp;gt; 10
&amp;#160;&amp;#160;&amp;#160; | Jack(_) -&amp;gt; 9
&amp;#160;&amp;#160;&amp;#160; | Value(n,_) -&amp;gt; n - 2

let suitOf (c:Card) =
&amp;#160;&amp;#160;&amp;#160; match c with
&amp;#160;&amp;#160;&amp;#160; | Ace(s) | King(s) | Queen(s) | Jack(s) | Value(_,s) -&amp;gt; s
&lt;/pre&gt;&lt;p&gt;As you can see, &lt;font size="2" face="Courier New"&gt;valueOf&lt;/font&gt; means nothing in terms of any card game, but allows us to easily see that &lt;font size="2" face="Courier New"&gt;valueOf(Value(9,Spades))&lt;/font&gt; &lt;font size="2" face="Courier New"&gt;&amp;lt;&lt;/font&gt; &lt;font size="2" face="Courier New"&gt;valueOf(King(Clubs))&lt;/font&gt; for example.&lt;/p&gt;&lt;p&gt;Now it gets tricky, bear with me through this, hopefully this para and following examples will clarify. I decided to come up with a standard type for each rank matching function. Each function needs to take a list of cards as its input, returning firstly &lt;font size="2" face="Courier New"&gt;true&lt;/font&gt; or &lt;font size="2" face="Courier New"&gt;false&lt;/font&gt; to indicate whether the hand matches that rank, but also returning two arrays of card values each in descending order - the first array is the values which are part of the rank (eg for two pairs, 9s and Aces, the array would be &lt;font size="2" face="Courier New"&gt;[| 12; 7 |]&lt;/font&gt;); and the second array is any cards which remain that are not in the rank (eg for a hand 9H 9C AS TD 2C this matches a pair of 9s with remaining array of &lt;font size="2" face="Courier New"&gt;[| 12; 8; 0 |]&lt;/font&gt;).&lt;/p&gt;&lt;p&gt;So the type of these functions is &lt;font size="2" face="Courier New"&gt;Card list -&amp;gt; bool * int [] * int []&lt;/font&gt; - we can use this to build a list of the ranking functions from highest (a royal flush) to the lowest (single card high), allowing us to try each in turn until one or both hands matches, and thus compare the hands. First I will define a few more helper functions that we will use in the ranking functions:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let desc n = -n

let allSameSuit (hand:Card list) =
&amp;#160;&amp;#160;&amp;#160; (hand |&amp;gt; Seq.map suitOf |&amp;gt; Seq.distinct |&amp;gt; Seq.length) = 1
&lt;/pre&gt;&lt;p&gt;The &lt;font size="2" face="Courier New"&gt;desc&lt;/font&gt; function is used for &lt;font size="2" face="Courier New"&gt;Seq.sortBy&lt;/font&gt; to reverse the order of an integer based sequence simply by negating the input, and &lt;font size="2" face="Courier New"&gt;allSameSuit&lt;/font&gt; is a predicate to determine when all the cards in a given hand belong to just one suit.&lt;/p&gt;&lt;h4&gt;MatchHighCard&lt;/h4&gt;&lt;p&gt;The lowest rank is X-High, meaning that the hand only contains single cards, and when comparing two hands of this rank, we compare card by card, until one hand has the higher card. Therefore any hand (which doesn't match a higher rank) will match this rank, and all cards in the hand are included in the rank, so appear in the first array, the second array being empty (as there are no remaining cards after those which belong to the rank are removed).&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let matchHighCard (hand:Card list) : (bool*int []*int []) =
&amp;#160;&amp;#160;&amp;#160; true, (hand |&amp;gt; Seq.map valueOf |&amp;gt; Seq.sortBy desc |&amp;gt; Array.ofSeq), [||]
&lt;/pre&gt;&lt;p&gt;So the implementation is pretty simple, true, followed by the card values in descending order.&lt;/p&gt;&lt;h4&gt;MatchTwoPairs&lt;/h4&gt;&lt;p&gt;The next example is for two pairs. Here we have two sets of two cards which are in the rank, and a single remaining card. &lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let matchTwoPairs (hand:Card list) : (bool*int []*int []) =
&amp;#160;&amp;#160;&amp;#160; let matches =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; hand |&amp;gt; Seq.map valueOf |&amp;gt; Seq.groupBy (fun n -&amp;gt; n)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; Seq.map (fun (n,s) -&amp;gt; n,(Seq.length s))
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; |&amp;gt; Seq.sortBy (fun (_,l) -&amp;gt; -l) |&amp;gt; Array.ofSeq
&amp;#160;&amp;#160;&amp;#160; if (Seq.length matches) &amp;lt;&amp;gt; 3 || (matches.[0] |&amp;gt; snd) &amp;lt;&amp;gt; 2 || (matches.[1] |&amp;gt; snd) &amp;lt;&amp;gt; 2 then false,[||],[||]
&amp;#160;&amp;#160;&amp;#160; else true,([| fst(matches.[0]); fst(matches.[1]) |] |&amp;gt; Array.sortBy desc),[| fst(matches.[2]) |]
&lt;/pre&gt;&lt;p&gt;This is one of the more complex implementations. We firstly get the card values and group by those values. &lt;font size="2" face="Courier New"&gt;Seq.groupBy&lt;/font&gt; gives us a sequence of tuples, the first value being the card value itself, the second is itself a sequence of each matching value (which is a bit nugatory in this case, as these are just sequences of the same value, hence in the following &lt;font size="2" face="Courier New"&gt;Seq.map&lt;/font&gt; we collapse these into just the number of occurrences). At this point we sort by the sequence length descending (using a custom lambda here as we are dealing with tuple values) and convert to an array for ease of indexing.&lt;/p&gt;&lt;p&gt;You probably need to see an example now. If the original hand was something like &lt;font size="2" face="Courier New"&gt;&amp;quot;9S JC 2D 2H JS&amp;quot;&lt;/font&gt;, we get a value sequence of seq &lt;font size="2" face="Courier New"&gt;[ 7; 9; 0; 0; 9 ]&lt;/font&gt;. Following all our mappings we are left with an array of tuples &lt;font size="2" face="Courier New"&gt;[| (9,2); (0,2); (7,1) |]&lt;/font&gt;. &lt;/p&gt;&lt;p&gt;Now we can check this array to see if it represents two pairs. It must have three elements, and the first two elements must represent pairs (the &lt;font size="2" face="Courier New"&gt;snd&lt;/font&gt; function gets the second value from the tuple, which is the number of occurrences of the given value). If these do not match, this isn't a rank of Two Pairs, so we return false and empty arrays.&lt;/p&gt;&lt;p&gt;If this is a match, we return true, with an array of two values (the highest of the pairs, then the lowest of the pairs), and finally the single remaining card value.&lt;/p&gt;&lt;h4&gt;MatchStraightFlush&lt;/h4&gt;&lt;p&gt;This is the last of my examples. A straight flush means the cards are all consecutive values, starting at any value, and they are all of the same suit.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let matchStraightFlush (hand:Card list) : (bool*int []*int []) =
&amp;#160;&amp;#160;&amp;#160; let values = hand |&amp;gt; List.map valueOf |&amp;gt; List.sort |&amp;gt; Seq.distinct |&amp;gt; Array.ofSeq
&amp;#160;&amp;#160;&amp;#160; if (Array.length values) &amp;lt;&amp;gt; 5 || (values.[4] - values.[0]) &amp;lt;&amp;gt; 4 || not (allSameSuit hand) then false,[||],[||]
&amp;#160;&amp;#160;&amp;#160; else true, [|values.[4]|], [||]
&lt;/pre&gt;&lt;p&gt;First we get the values, sort and remove duplicates (if there are dups, it can't be a straight - we check for this next). So now, if we don't have 5 cards, this isn't a match, or if the highest value - lowest value is not 4, then they are not consecutive, so not a match, or if they are not all the same suit, it isn't a match.&lt;/p&gt;&lt;p&gt;Where we have a match, the value of the highest card in the straight is returned.&lt;/p&gt;&lt;h3&gt;Comparing the Hands&lt;/h3&gt;&lt;p&gt;Lets define a utility function first. This takes two arrays, comparing item by item until a difference is found, returning negative to indicate the first array is greater, positive if the second array is greater, 0 if they are equal. We will use this to compare cards when two hands are of the same rank.&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let compArrays (a:int [], b:int []) =
&amp;#160;&amp;#160;&amp;#160; if Array.length(a) &amp;lt;&amp;gt; Array.length(b) then failwith &amp;quot;Array lengths differ&amp;quot;
&amp;#160;&amp;#160;&amp;#160; let rec innerCompArrays (a:int [], b:int [],n) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if n = Array.length(a) then 0
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if a.[n] &amp;lt;&amp;gt; b.[n] then b.[n] - a.[n]
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else innerCompArrays(a,b,(n+1))
&amp;#160;&amp;#160;&amp;#160; innerCompArrays(a,b,0)
&lt;/pre&gt;&lt;p&gt;Note the array lengths must be equal, and we assume they are both in the same order. We use a simple recursive function to step through item by item until the end of the array is reached, or a difference is found.&lt;/p&gt;&lt;p&gt;Now we can define our ordered list of match functions (note there are more than shown above, other implementations left as an exercise for the reader):&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;let matchFuncs =
&amp;#160;&amp;#160;&amp;#160; [   matchRoyalFlush
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchStraightFlush
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchFourOfAKind
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchFullHouse
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchFlush
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchStraight
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchThreeOfAKind
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchTwoPairs
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchAPair
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; matchHighCard
&amp;#160;&amp;#160;&amp;#160; ]
&lt;/pre&gt;&lt;p&gt;We finally have everything we need to do the comparison of two poker hands. We can bring this all together in a single function which itself iterates over the above list of functions until a match is found for one or both hands, then, if needed, comparing the cards in the hand and then remaining cards to find a winner:&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;type matchFunc = (Card list) -&amp;gt; (bool * int [] * int [])

let compareHands (hands:string) =
&amp;#160;&amp;#160;&amp;#160; let rec innerCompareHands (handA:Card list, handB:Card list, funcs:matchFunc list) =
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; match funcs with
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | [] -&amp;gt; failwith &amp;quot;No Winning Hand!&amp;quot;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | f::tail -&amp;gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let mtchA,incA,remainA = f(handA)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let mtchB,incB,remainB = f(handB)
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; match mtchA,mtchB with
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | true,false -&amp;gt; 1
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | false,true -&amp;gt; -1
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | true,true -&amp;gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; let c = compare incA incB
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if c &amp;lt;&amp;gt; 0 then c
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else compare remainA remainB
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; | false,false -&amp;gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; innerCompareHands (handA,handB,tail)
&amp;#160;&amp;#160;&amp;#160; let handA, handB = parseHands(hands)
&amp;#160;&amp;#160;&amp;#160; if innerCompareHands (handA, handB, matchFuncs) &amp;gt; 0 then 1 else 2
&lt;/pre&gt;&lt;p&gt;UPDATE: Realised that the &lt;font size="2" face="Courier New"&gt;compArrays&lt;/font&gt; function was redundant, as the F# &lt;font size="2" face="Courier New"&gt;compare&lt;/font&gt; function works as well with lists and arrays as it does with simpler values. Updated the above accordingly.&lt;/p&gt;&lt;p&gt;Here we parse the string containing the two hands into the separate hands, then iterate over this using the inner recursive function. We work through each function in the list, testing both hands, then the inner pattern match checks the two match results side by side to find an outright winner (&lt;font size="2" face="Courier New"&gt;false,true&lt;/font&gt; or &lt;font size="2" face="Courier New"&gt;true,false&lt;/font&gt;) a draw (&lt;font size="2" face="Courier New"&gt;true,true&lt;/font&gt;) in which case we compare first the cards in the matching rank, then the remaining cards if still a draw. If there are no matches for this function, we move to the next rank and test for that. Note that the check for no remaining functions isn't ever going to be exercised as &lt;font size="2" face="Courier New"&gt;matchHighCard&lt;/font&gt; will always match. The final result indicates a win for player 1 or player 2&lt;/p&gt;&lt;pre class="brush: fsharp; ruler: true; auto-links: false"&gt;&amp;gt; compareHands &amp;quot;JH 2D 3S JC AS 7D 3C AH 7C 7S&amp;quot;;;
val it : int = 2
&amp;gt; compareHands &amp;quot;TS JS QS KS AS 7D 3C AH 7C 7S&amp;quot;;;
val it : int = 1&lt;/pre&gt;&lt;p&gt;We can see this works fine - in the first example the second hand (three 7s) beats the first (pair of Jacks), and in the second example, the first hand wins as it is a Royal Flush.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;We can see that F# code really lends itself to breaking down a problem like this. We use discriminated unions to represent our model very succinctly. We use pattern matching for parsing and checking card values, we use higher order functions on sequences and arrays to concisely compose our rank matching functions, and we use an array of these functions just as easily as any other data type to build our final comparison routine.&lt;/p&gt;&lt;p&gt;With some work, I could probably make this even more succinct, maybe by using active patterns to replace the recursion over the array of functions with a pattern matching expression instead, but hopefully the above demonstrates that a &amp;quot;good enough&amp;quot; solution has been achieved. In case you are interested, the final result is calculated in 188ms, including reading the file.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-4039275667715824485?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/qE-mcMzyZbI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/4039275667715824485/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=4039275667715824485" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/4039275667715824485?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/4039275667715824485?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/qE-mcMzyZbI/my-first-f-post.html" title="My First F# Post" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/06/my-first-f-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUGQ348eSp7ImA9WxFTE0Q.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-1891416632297012302</id><published>2010-04-04T12:19:00.004+01:00</published><updated>2010-04-04T17:07:02.071+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-04T17:07:02.071+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="MIX" /><category scheme="http://www.blogger.com/atom/ns#" term="OData" /><title>Building an OData consumer for Windows Phone 7 Series, Part 2</title><content type="html">In &lt;a href="http://blog.roundthecampfire.net/2010/04/building-odata-consumer-for-windows.html" target="_blank"&gt;Part 1&lt;/a&gt; I talked about the rough outline of the application – a WP7S app which talks to a publically available OData service (the NerdDinner service) and presents a master detail view of this, with geographical data. We looked at installing the tools, building a WP7S application, and walked around the architecture of the application.&lt;br /&gt;
&lt;br /&gt;
Today I will add the OData service call and implement binding from the master view to the data retrieved, and make sure that this data is rendered in the list in a pleasing manner.&lt;br /&gt;
&lt;h4&gt;Calling the OData Service&lt;/h4&gt;If you haven’t done so already, download the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b251b247-70ca-4887-bab6-dccdec192f8d&amp;amp;displaylang=en" target="_blank"&gt;OData client library&lt;/a&gt; and unzip the files into a local directory. Add a reference from the NerdDinnerFinder project to &lt;span style="font-family: Courier New; font-size: small;"&gt;System.Data.Services.Client.dll&lt;/span&gt;. &lt;br /&gt;
Currently there is no documentation available specifically for WP7S, but &lt;a href="http://blogs.msdn.com/phaniraj/archive/2010/03/19/developing-a-windows-phone-7-application-that-consumes-odata.aspx" target="_blank"&gt;this blog post&lt;/a&gt; by Well Phani describes how to add a service reference using the &lt;span style="font-family: Courier New; font-size: small;"&gt;DataSvcutil.exe &lt;/span&gt;tool in the framework 4.0 directory.&lt;br /&gt;
&lt;br /&gt;
Using an Admin command prompt, navigate to the NerdDinnerFinder project directory, then execute this command:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;%WINDIR%\Microsoft.NET\Framework\v4.0.30128\DataSvcUtil.exe /?&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This gives the following output:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Microsoft (R) DataSvcUtil version 4.0.0.0
Copyright (C) 2008 Microsoft Corporation. All rights reserved.

DataSvcUtil Options
/in:&amp;lt;file&amp;gt;               The file to read the conceptual model from
/out:&amp;lt;file&amp;gt;              The file to write the generated object layer to
/language:CSharp         Generate code using the C# language
/language:VB             Generate code using the VB language
/Version:1.0             Accept CSDL documents tagged with
m:DataServiceVersion=1.0 or lower
/Version:2.0             Accept CSDL documents tagged with
m:DataServiceVersion=2.0 or lower
/DataServiceCollection   Generate collections derived from DataServiceCollection
/uri:&amp;lt;URL&amp;gt;               The URI to read the conceptual model from
/help                    Display the usage message (short form: /?)
/nologo                  Suppress copyright message

Examples
To generate code from a data service.
DataSvcUtil /out:"data.cs" /uri:"http://localhost/data.svc"

To generate code from a conceptual model file.
DataSvcUtil /out:"data.cs" /in:"file.csdl"

To generate code from a entity design model file.
DataSvcUtil /out:"data.cs" /in:"file.edmx"&lt;/pre&gt;&lt;br /&gt;
So using the blog post above as guidance, we can generate our classes directly from the live OData service by using the command":&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: Courier New; font-size: small;"&gt;%WINDIR%\Microsoft.NET\Framework\v4.0.30128\DataSvcUtil.exe&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /uri:http://&lt;a href="http://www.nerddinner.com/Services/OData.svc/" title="http://www.nerddinner.com/Services/OData.svc/"&gt;www.nerddinner.com/Services/OData.svc/&lt;/a&gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /DataServiceCollection /Version:2.0 /out:nerdDinnerService.cs&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
This creates the file &lt;span style="font-family: Courier New; font-size: small;"&gt;nerdDinnerService.cs &lt;/span&gt;which we can now directly include in our project, and take a look at. What we have is a fairly standard looking codegen file with three classes: &lt;span style="font-family: Courier New; font-size: small;"&gt;NerdDinnerEntities&lt;/span&gt;, &lt;span style="font-family: Courier New; font-size: small;"&gt;Dinner &lt;/span&gt;and &lt;span style="font-family: Courier New; font-size: small;"&gt;RSVP &lt;/span&gt;under the &lt;span style="font-family: Courier New; font-size: small;"&gt;NerdDinnerModel &lt;/span&gt;namespace. The NerdDinnerEntities class is our entry point, and derives from &lt;span style="font-family: Courier New; font-size: small;"&gt;DataServiceContext &lt;/span&gt;in &lt;span style="font-family: Courier New; font-size: small;"&gt;System.Data.Services.Client&lt;/span&gt;. The other two classes are our data objects.&lt;br /&gt;
&lt;br /&gt;
Experimenting with the &lt;span style="font-family: Courier New; font-size: small;"&gt;NerdDinnerEntities &lt;/span&gt;class, there doesn’t appear to be any obvious ‘Linqy’ way to deal with the data. If I try to directly bind to the &lt;span style="font-family: Courier New; font-size: small;"&gt;Dinners &lt;/span&gt;collection it comes back with an opaque &lt;span style="font-family: Courier New; font-size: small;"&gt;NotSupportedException &lt;/span&gt;which isn’t much help. Just for the sake of getting things moving, lets use the &lt;span style="font-family: Courier New; font-size: small;"&gt;BeginExecute&amp;lt;T&amp;gt;&lt;/span&gt; and &lt;span style="font-family: Courier New; font-size: small;"&gt;EndExecute &lt;/span&gt;methods:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Reset page transition
&amp;nbsp;&amp;nbsp;&amp;nbsp; ResetPageTransitionList.Begin();

&amp;nbsp;&amp;nbsp;&amp;nbsp; context = new NerdDinnerEntities(new Uri(&lt;a href="http://www.nerddinner.com/Services/OData.svc"&gt;http://www.nerddinner.com/Services/OData.svc&lt;/a&gt;));
&amp;nbsp;&amp;nbsp;&amp;nbsp; context.BeginExecute&amp;lt;Dinner&amp;gt;(new Uri("/Dinners",UriKind.Relative), DinnerReady, null);
}

private void DinnerReady(IAsyncResult asyncResult)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; Deployment.Current.Dispatcher.BeginInvoke(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; () =&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;Dinner&amp;gt; results = context.EndExecute&amp;lt;Dinner&amp;gt;(asyncResult).ToList() as IEnumerable&amp;lt;Dinner&amp;gt;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lstDinners.ItemsSource = results;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );
}&lt;/pre&gt;&lt;br /&gt;
This seems heavy handed, as we have to hand code the relative URI, but it does seem to work. In order to get this to display correctly, we will need to make some changes to the xaml (we should change the name of the list box, and make some changes to the &lt;span style="font-family: Courier New; font-size: small;"&gt;ItemTemplate &lt;/span&gt;in order to get the sample listbox to bind to the data we are returning). Replace the entire ListBox element with the following:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml; ruler: true; auto-links: false;"&gt;&amp;lt;ListBox x:Name="lstDinners" MouseLeftButtonUp="ListBoxOne_MouseLeftButtonUp" 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Style="{StaticResource PhoneListBox}"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ListBox.ItemTemplate&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DataTemplate&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StackPanel x:Name="DataTemplateStackPanel" Orientation="Vertical"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextLargeStyle}" /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Description}" Style="{StaticResource PhoneTextNormalStyle}" /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/StackPanel&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/DataTemplate&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ListBox.ItemTemplate&amp;gt;
&amp;lt;/ListBox&amp;gt;&lt;/pre&gt;&lt;br /&gt;
So we change the name, remove the declarative data binding from &lt;span style="font-family: Courier New; font-size: small;"&gt;ItemsSource &lt;/span&gt;and update the &lt;span style="font-family: Courier New; font-size: small;"&gt;ItemTemplate &lt;/span&gt;with a more simple view onto our &lt;span style="font-family: Courier New; font-size: small;"&gt;Dinner &lt;/span&gt;items. If we run this now, we should get a sensible result:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh6.ggpht.com/_bqE0F2FFSYA/S7ejr4JXQBI/AAAAAAAAADY/DQ_QvMD3z_E/s1600-h/master-page-complete%5B9%5D.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="master-page-complete" border="0" height="480" src="http://lh6.ggpht.com/_bqE0F2FFSYA/S7ejsbG1L4I/AAAAAAAAADc/DaFkBmaWqPc/master-page-complete_thumb%5B5%5D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="master-page-complete" width="294" /&gt;&lt;/a&gt;&lt;/div&gt;This is our master view, now we need to change the item selection event handler to navigate from this page to the detail page - it already does, but we need to pass in the Id of the selected dinner, so some tweaks are required.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;private void ListBoxOne_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Capture selected item data
&amp;nbsp;&amp;nbsp;&amp;nbsp; selectedItem = (sender as ListBox).SelectedItem as Dinner;

&amp;nbsp;&amp;nbsp;&amp;nbsp; // Start page transition animation
&amp;nbsp;&amp;nbsp;&amp;nbsp; PageTransitionList.Begin();
}

private void PageTransitionList_Completed(object sender, EventArgs e)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set datacontext of details page to selected listbox item
&amp;nbsp;&amp;nbsp;&amp;nbsp; NavigationService.Navigate(new Uri(String.Format("/DetailsPage.xaml?id={0}",selectedItem.DinnerID), UriKind.Relative));
}&lt;/pre&gt;&lt;br /&gt;
Note the change to &lt;span style="font-family: Courier New; font-size: small;"&gt;NavigationService.Navigate &lt;/span&gt;– by passing in the id as a query string parameter, we can ensure that the navigation will work even with application dehydration/rehydration. With this in place we can make the corresponding change in &lt;span style="font-family: Courier New; font-size: small;"&gt;DetailsPage.xaml.cs &lt;/span&gt;and then we are ready to implement the details view.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml; ruler: true; auto-links: false;"&gt;&amp;lt;Grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}" d:DataContext="{Binding Items[0]}"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid.RowDefinitions&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;RowDefinition Height="Auto"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;RowDefinition Height="*"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid.RowDefinitions&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--TitleGrid is the name of the application and page title--&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid x:Name="TitleGrid" Grid.Row="0"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid.Projection&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PlaneProjection/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid.Projection&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="NERD DINNER FINDER" Style="{StaticResource PhoneTextPageTitle1Style}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextPageTitle2Style}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--ContentGrid contains the details--&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid x:Name="ContentGrid" Grid.Row="1"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Grid.Projection&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PlaneProjection/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid.Projection&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StackPanel Orientation="Vertical"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding Description}" Margin="20,0,20,0" TextWrapping="Wrap" Style="{StaticResource PhoneTextSmallStyle}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;StackPanel Orientation="Horizontal"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="Hosted by " Style="{StaticResource PhoneTextBodyTextStyle}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TextBlock Text="{Binding HostedBy}" Style="{StaticResource PhoneTextBodyTextStyle}"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/StackPanel&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/StackPanel&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Grid&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;&lt;br /&gt;
This ensures that the current item (which is bound to the page itself) is used to populate the various text boxes on this page. The result gets us where we need to be for today:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh4.ggpht.com/_bqE0F2FFSYA/S7ejswMBN4I/AAAAAAAAADg/1ulMW9WKpug/s1600-h/detail-page-firsteffort%5B5%5D.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="detail-page-firsteffort" border="0" height="480" src="http://lh3.ggpht.com/_bqE0F2FFSYA/S7ejtqjpgoI/AAAAAAAAADk/ZOrVxft5euQ/detail-page-firsteffort_thumb%5B3%5D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="detail-page-firsteffort" width="295" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;Round Up&lt;/h4&gt;Today we have installed the OData client library, struggled a little bit in understanding the model this exposes (a little documentation here would help a lot), and come up with a 50% elegant solution for bringing in the data we need and binding this within the master view and the detail view.&lt;br /&gt;
&lt;br /&gt;
In the final article, I will try and make use of the geographical data we get back from this service to enable an inset map showing the location of the event on the details page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-1891416632297012302?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/2KxiOT2iR_0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/1891416632297012302/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=1891416632297012302" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1891416632297012302?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1891416632297012302?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/2KxiOT2iR_0/building-odata-consumer-for-windows_04.html" title="Building an OData consumer for Windows Phone 7 Series, Part 2" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/_bqE0F2FFSYA/S7ejsbG1L4I/AAAAAAAAADc/DaFkBmaWqPc/s72-c/master-page-complete_thumb%5B5%5D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/04/building-odata-consumer-for-windows_04.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IMQ3kzeCp7ImA9WxFTE0U.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-1038901058679486391</id><published>2010-04-02T22:32:00.004+01:00</published><updated>2010-04-04T14:59:42.780+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-04T14:59:42.780+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="Windows Phone 7" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><category scheme="http://www.blogger.com/atom/ns#" term="MIX" /><category scheme="http://www.blogger.com/atom/ns#" term="OData" /><title>Building an OData consumer for Windows Phone 7 Series, Part 1</title><content type="html">Having recently returned from MIX 2010, two of the technologies which stuck in my mind were &lt;a href="http://www.odata.org/"&gt;OData&lt;/a&gt; (and specifically the latest incarnation of project Astoria - &lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx"&gt;WCF Data Services&lt;/a&gt;) and of course the first CTP of the Windows Phone 7 series SDK. &lt;br /&gt;
&lt;br /&gt;
I am already working on a WP7S application for the marketplace, but I thought it would be an interesting aside to put together a bit of a mash-up application which consumes an OData service, presents a pleasing view over this data using silverlight, and supports viewing location data using Bing maps. I will document the construction of this application in three parts, this being the first. &lt;br /&gt;
&lt;h4&gt;Finding an OData Service&lt;/h4&gt;We could, of course, write our own OData service against the Northwind database or similar, but for the sake of simplicity, I thought it would be better to consume one of the sample services from the OData site. For this demonstration I will use the &lt;a href="http://www.nerddinner.com/Services/OData.svc/"&gt;NerdDinner Service&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_bqE0F2FFSYA/S7Yigs7L2mI/AAAAAAAAACg/qzsZQX55mFA/s1600/nerddinner-svc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="177" src="http://2.bp.blogspot.com/_bqE0F2FFSYA/S7Yigs7L2mI/AAAAAAAAACg/qzsZQX55mFA/s640/nerddinner-svc.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;As you can see, this is a pretty basic service at the moment, but will suffice for this demonstration. What we would like to do is drill down into the &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;Dinners&lt;/span&gt; category, present a list of available dinners, and then provide an interface to drill down into a particular dinner and show the details (including the location). &lt;br /&gt;
&lt;h4&gt;Getting Started&lt;/h4&gt;In order to develop this application you will need to download and install the following components: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=2338b5d1-79d8-46af-b828-380b0f854203&amp;amp;displaylang=en"&gt;Windows Phone 7 Series Developer Tools&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=b251b247-70ca-4887-bab6-dccdec192f8d&amp;amp;displaylang=en"&gt;OData Client Library for Windows Phone 7 Series&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;The first link will download everything you need to develop for WP7S - Visual Studio 2010 Express Edition, the WP7S Emulator, Silverlight SDK and XNA Game studio. Note that if you already have an edition of VS 2010 installed, it will also install the necessary project templates for that. &lt;br /&gt;
&lt;h3&gt;Creating the Application&lt;/h3&gt;We can make use of existing project templates to get us started quickly. Launch VS2010 and create a new project from &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;Visual C# &amp;gt; Silverlight for Windows Phone &amp;gt; Windows Phone List Application&lt;/span&gt;. Name the project &amp;amp; solution &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;NerdDinnerFinder&lt;/span&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_bqE0F2FFSYA/S7Yod7QCs-I/AAAAAAAAACo/GmS5EJZuh4g/s1600/new-project.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="356" src="http://2.bp.blogspot.com/_bqE0F2FFSYA/S7Yod7QCs-I/AAAAAAAAACo/GmS5EJZuh4g/s640/new-project.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
This will create a new windows phone project which contains the application (&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;App.xaml&lt;/span&gt;) and two silverlight pages (&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;MainPage.xaml&lt;/span&gt; and &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;DetailsPage.xaml&lt;/span&gt;). If we open up the designer for &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;MainPage.xaml&lt;/span&gt;, we can see the design view of the page as it would look on the phone, side by side with the xaml code. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7YrgcOj0OI/AAAAAAAAACw/LVS3CY4qbHQ/s1600/mainpage-just-created.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7YrgcOj0OI/AAAAAAAAACw/LVS3CY4qbHQ/s400/mainpage-just-created.png" width="208" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Notice that this has already created us a master/details view in effect, so all we need to do is plumb in the OData service to these xaml pages. If you build and run this application as it stands, it will launch the WP7S emulator (which takes about a minute to load the first time, but thereafter very quick as long as you leave it running). &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7YvFCgUF7I/AAAAAAAAAC4/8YPlJI3TqWg/s1600/emulator-template-app.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="371" src="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7YvFCgUF7I/AAAAAAAAAC4/8YPlJI3TqWg/s400/emulator-template-app.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;h4&gt;Examining the Build Output&lt;/h4&gt;It's always good to try and ensure we get a deeper understanding of what happens under the hood. Lets take a look at the artifacts produced by this build, and see what they have to show us: &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7Y0JFlQgwI/AAAAAAAAADA/Sh0OGdzj6pU/s1600/build-output.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" src="http://1.bp.blogspot.com/_bqE0F2FFSYA/S7Y0JFlQgwI/AAAAAAAAADA/Sh0OGdzj6pU/s400/build-output.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;NerdDinnerFinder.xap &lt;/span&gt;file is actually the single file which will be deployed to the device. We can use a trick from the silverlight development toolbox to see what this file contains - simply rename it with a .&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;zip&lt;/span&gt; extension and open it in explorer. Within this we can see the same files, and one additional - &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;WMAppManifest.xml&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. &lt;br /&gt;
&lt;br /&gt;
We therefore have two .&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;png &lt;/span&gt;files to store various size of icon imagery for the use of the phone OS, we have the actual &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;dll&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;and &lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: &amp;quot;Courier New&amp;quot;, courier, monospace;"&gt;pdb&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;for our single project, then two manifest files. &lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;AppManifest.xaml &lt;/span&gt;simply describes the application and the binary files of which it is comprised: &lt;br /&gt;
&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; EntryPointAssembly="NerdDinnerFinder" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; EntryPointType="NerdDinnerFinder.App" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; RuntimeVersion="3.0.40624.0"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Deployment.Parts&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;AssemblyPart x:Name="NerdDinnerFinder" Source="NerdDinnerFinder.dll" /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Deployment.Parts&amp;gt;
&amp;lt;/Deployment&amp;gt;
&lt;/pre&gt;The other file &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;WMAppManifest.xml &lt;/span&gt;would appear to be the means of defining the resources and capabilities of the app from the point of view of the OS, i.e. as the place where it can get icons and images for the app: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;App xmlns="" ProductID="{45a8bc14-719e-4920-bce2-57e11d08e8bb}" Title="NerdDinnerFinder" RuntimeType="SilverLight" Version="1.0.0.0" Genre="NormalApp"&amp;nbsp;&amp;nbsp;&amp;nbsp; Author="" Description="" Publisher=""&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;IconPath IsRelative="true" IsResource="false"&amp;gt;ApplicationIcon.png&amp;lt;/IconPath&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Capabilities&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Capabilities&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Tasks&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;DefaultTask Name="_default" PlaceHolderString="Default task"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Tasks&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Tokens&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;PrimaryToken TokenID="NerdDinnerFinderToken" TaskName="_default"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;TemplateType5&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;BackgroundImageURI IsRelative="true" IsResource="false"&amp;gt;Background.png&amp;lt;/BackgroundImageURI&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Count&amp;gt;0&amp;lt;/Count&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Title&amp;gt;NerdDinnerFinder&amp;lt;/Title&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/TemplateType5&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/PrimaryToken&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Tokens&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/App&amp;gt;
&amp;lt;/Deployment&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
I thought maybe we could influence some of the attribute settings under App by modifying the project preferences as follows: &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh5.ggpht.com/_bqE0F2FFSYA/S7ZKfrOoi3I/AAAAAAAAADI/_a5LYp9F-jQ/s1600-h/application-settings%5B10%5D.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="application-settings" border="0" height="409" src="http://lh6.ggpht.com/_bqE0F2FFSYA/S7ZKgZjaEPI/AAAAAAAAADM/na-Jyn6pidU/application-settings_thumb%5B6%5D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="application-settings" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
But recompiling using these settings showed no change in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;WMAppManifest.xml &lt;/span&gt;file. My guess would be this is the file in which the Windows Phone Marketplace team will put all the metadata and code signing stuff when your app gets approved.&lt;br /&gt;
&lt;h4&gt;Anatomy of the Windows Phone 7 Series DLL&lt;/h4&gt;Now we have looked at the contents of the .&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;xap &lt;/span&gt;file, lets crack open the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;NerdDinnerFinder.dll &lt;/span&gt;file and see if there is anything unexpected in there: &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://lh6.ggpht.com/_bqE0F2FFSYA/S7ZKhdZa0MI/AAAAAAAAADQ/c5uo8jE9JXM/s1600-h/reflector%5B5%5D.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="reflector" border="0" height="414" src="http://lh5.ggpht.com/_bqE0F2FFSYA/S7ZKiWF1WNI/AAAAAAAAADU/Lye8gqKLVb0/reflector_thumb%5B3%5D.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="reflector" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
As we might expect, we have a Page class for the two pages, some viewmodel classes and the App class. We also have all the .&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;xaml &lt;/span&gt;files packaged as resources. The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;TargetFramework &lt;/span&gt;assembly level attribute shows “&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;Silverlight,Version=v4.0,Profile=WindowsPhone&lt;/span&gt;”. This is slightly strange, as the standard line in MIX was that WP7S is silverlight 3 with some extra bits, whereas this seems to indicate we have silverlight 4, but with some bits taken away…&lt;br /&gt;
&lt;h3&gt;Structure of the Windows Phone Application&lt;/h3&gt;Lets dig around the solution in visual studio now, starting with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;App.xaml.&lt;/span&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;App.xaml&lt;/h4&gt;This defines the application itself, and is configured in the project settings (see previous section) as the startup object for the solution. The file created by the visual studio template is quite large, as it is used to define a large number of xaml resources for use throughout the application, but starts like so: &lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: xml; ruler: true; auto-links: false"&gt;&amp;lt;Application 
&amp;nbsp;&amp;nbsp;&amp;nbsp; x:Class="NerdDinnerFinder.App"
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:system="clr-namespace:System;assembly=mscorlib"
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:mpc="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:phoneNavigation="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Navigation"&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--RootFrame points to and loads the first page of your application--&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Application.RootVisual&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;phoneNavigation:PhoneApplicationFrame x:Name="RootFrame" Source="/MainPage.xaml"/&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Application.RootVisual&amp;gt;

&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Resources for following the Windows Phone design guidelines --&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Application.Resources&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--************ THEME RESOURCES ************--&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!-- Color Resources --&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Color x:Key="PhoneBackgroundColor"&amp;gt;#FF1F1F1F&amp;lt;/Color&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Color x:Key="PhoneContrastForegroundColor"&amp;gt;Black&amp;lt;/Color&amp;gt;
...
&amp;lt;/Application&amp;gt;&lt;/pre&gt;&lt;br /&gt;
Deconstructing this file, we can see there are two main purposes – firstly it defines the root visual, or “entry page” for the application as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;MainPage.xaml&lt;/span&gt;, secondly it defines resources for the rest of the application. &lt;br /&gt;
&lt;br /&gt;
There is a codebehind file, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;App.xaml.cs&lt;/span&gt;, which currently is used to hook up an event handler for all unhandled exceptions. &lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;MainPage.xaml&lt;/h4&gt;This is just a standard &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;xaml &lt;/span&gt;page, derived from &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;PhoneApplicationPage &lt;/span&gt;and defines a simple layout with headings and a list box with an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;ItemTemplate&lt;/span&gt;. The codebehind, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;MainPage.xaml.cs&lt;/span&gt;, defines a transition effect to occur when a list item is clicked, and in the completion handler calls &lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: small;"&gt;NavigationService.Navigate &lt;/span&gt;to move to the detail page. &lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Summary&lt;/h3&gt;So far we have determined what we want to demonstrate with this application, installed the required development tools, created a basic application from the windows phone list application template, and taken a look around this application. &lt;br /&gt;
&lt;br /&gt;
Next up, we will hook up an OData client within this application and bind this to the listbox.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-1038901058679486391?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/3TkcacMpGZU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/1038901058679486391/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=1038901058679486391" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1038901058679486391?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1038901058679486391?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/3TkcacMpGZU/building-odata-consumer-for-windows.html" title="Building an OData consumer for Windows Phone 7 Series, Part 1" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_bqE0F2FFSYA/S7Yigs7L2mI/AAAAAAAAACg/qzsZQX55mFA/s72-c/nerddinner-svc.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/04/building-odata-consumer-for-windows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04CQXo9eSp7ImA9WxFTEkw.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-1919655231611614821</id><published>2010-02-14T20:00:00.000Z</published><updated>2010-04-02T13:39:20.461+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-02T13:39:20.461+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="T4" /><category scheme="http://www.blogger.com/atom/ns#" term="VS2010" /><category scheme="http://www.blogger.com/atom/ns#" term="DGML" /><title>Using DGML in Visual Studio 2010 to visualise a financial model</title><content type="html">&lt;p&gt;Having just installed the new RC of Visual Studio 2010, and prompted by &lt;a href="http://www.lovettsoftware.com/videos/GraphDocuments.wmv" target="_blank"&gt;this video by Chris Lovett&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/camerons/archive/2008/12/16/introduction-to-directed-graph-markup-language-dgml.aspx" target="_blank"&gt;these blog posts by Cameron Skinner&lt;/a&gt;  it prompted me to experiment with an idea I had a while ago – the ability to generate a diagram showing the calculations and the flow of values for a financial model.&lt;/p&gt;&lt;p&gt;In this experiment I will create a simplistic &lt;a href="http://en.wikipedia.org/wiki/Bond_pricing" target="_blank"&gt;bond pricer&lt;/a&gt; in C#, create a logging mechanism for this model to output values at the various stages, and then implement a means to transform these values into a DGML model file which we can then visualise.&lt;/p&gt;&lt;h4&gt;Create a logging mechanism&lt;/h4&gt;&lt;p&gt;All we need is a means to generate an XML document containing the Inputs, Simple calculations, and iterated calculations (this is enough to satisfy the requirements of the simple bond pricer)&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;    public class XmlLogger : ICalcLogger&lt;br /&gt;    {&lt;br /&gt;        public XDocument LoggedValues { get; private set; }&lt;br /&gt;&lt;br /&gt;        public XmlLogger()&lt;br /&gt;        {&lt;br /&gt;            LoggedValues = new XDocument();&lt;br /&gt;&lt;br /&gt;            LoggedValues.Add(new XElement("Results",&lt;br /&gt;                new XElement("Inputs"),&lt;br /&gt;                new XElement("SingleCalcs"),&lt;br /&gt;                new XElement("IteratedCalcs")));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Save(string filename)&lt;br /&gt;        {&lt;br /&gt;            File.WriteAllText(filename, LoggedValues.ToString());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void LogInput(string name, object value)&lt;br /&gt;        {&lt;br /&gt;            LoggedValues.Element("Results").Element("Inputs").Add(&lt;br /&gt;                new XElement("Input",&lt;br /&gt;                    new XAttribute("name", name),&lt;br /&gt;                    new XAttribute("category", "Inputs"),&lt;br /&gt;                    new XAttribute("value", value)));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void LogSingleCalc(string name, string category, string formula, object value)&lt;br /&gt;        {&lt;br /&gt;            LoggedValues.Element("Results").Element("SingleCalcs").Add(&lt;br /&gt;                new XElement("SingleCalc",&lt;br /&gt;                    new XAttribute("name", name),&lt;br /&gt;                    new XAttribute("category", category),&lt;br /&gt;                    new XAttribute("formula", formula),&lt;br /&gt;                    new XAttribute("value", value)));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void LogIteratedCalc(string name, string category, int iteration, string formula, object value)&lt;br /&gt;        {&lt;br /&gt;            LoggedValues.Element("Results").Element("IteratedCalcs").Add(&lt;br /&gt;                new XElement("IteratedCalc",&lt;br /&gt;                    new XAttribute("name", name),&lt;br /&gt;                    new XAttribute("category", category),&lt;br /&gt;                    new XAttribute("iteration", iteration),&lt;br /&gt;                    new XAttribute("formula", formula),&lt;br /&gt;                    new XAttribute("value", value)));&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;h4&gt;Create the Bond Pricer model&lt;/h4&gt;&lt;p&gt;With the logging in place, we can now create an implementation of the bond pricer which makes use of this logging:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;    // very basic clean price calculation based on http://en.wikipedia.org/wiki/Bond_pricing&lt;br /&gt;    public class SimpleBondPricer&lt;br /&gt;    {&lt;br /&gt;        private double F;&lt;br /&gt;        private double C;&lt;br /&gt;        private double r;&lt;br /&gt;        private int T;&lt;br /&gt;        private int n;&lt;br /&gt;        private ICalcLogger logger;&lt;br /&gt;&lt;br /&gt;        public SimpleBondPricer(double F, double C, double r, int T, int n, ICalcLogger logger)&lt;br /&gt;        {&lt;br /&gt;            this.F = F;&lt;br /&gt;            this.C = C;&lt;br /&gt;            this.r = r;&lt;br /&gt;            this.T = T;&lt;br /&gt;            this.n = n;&lt;br /&gt;            this.logger = logger;&lt;br /&gt;&lt;br /&gt;            logger.LogInput("F", F);&lt;br /&gt;            logger.LogInput("C", C);&lt;br /&gt;            logger.LogInput("r", r);&lt;br /&gt;            logger.LogInput("T", T);&lt;br /&gt;            logger.LogInput("n", n);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public double CalculatePrice()&lt;br /&gt;        {&lt;br /&gt;            double coupons = CalculateCoupons(logger);&lt;br /&gt;            double discountedFace = CalculatedDiscountedFaceValue(logger);&lt;br /&gt;&lt;br /&gt;            double result = discountedFace + coupons;&lt;br /&gt;            logger.LogSingleCalc("Pc", "Results", "Sm+DF", result);&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private double CalculatedDiscountedFaceValue(ICalcLogger logger)&lt;br /&gt;        {&lt;br /&gt;            double result = F / Math.Pow(1.0 + r, T);&lt;br /&gt;            logger.LogSingleCalc("DF", "ParCalcs", "F / (1+r)^T", result);&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private double CalculateCoupons(ICalcLogger logger)&lt;br /&gt;        {&lt;br /&gt;            int m = n * T;&lt;br /&gt;            logger.LogSingleCalc("m", "CouponCalcs", "n.T", m);&lt;br /&gt;&lt;br /&gt;            double u = Math.Pow(1.0 + r, 1.0 / n);&lt;br /&gt;            logger.LogSingleCalc("u", "CouponCalcs", "(1 + r) ^ (1 / n)", u);&lt;br /&gt;&lt;br /&gt;            double result = 0.0;&lt;br /&gt;            for (int t = 1; t &amp;lt;= m; t++)&lt;br /&gt;            {&lt;br /&gt;                double iterationResult = C / Math.Pow(u, t);&lt;br /&gt;                logger.LogIteratedCalc("S", "CouponCalcs", t, "C/u^t", iterationResult);&lt;br /&gt;                result += iterationResult;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            logger.LogSingleCalc("Sm", "CouponCalcs", "Sum[t=1..m](C/u^t)", result);&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;p&gt;So we ensure all inputs are logged once we get them, and each stage in the calculation we log the formula used and the results obtained. So a simple invocation such as:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;    var logger = new XmlLogger();&lt;br /&gt;&lt;br /&gt;    var bp = new SimpleBondPricer(100.0, 0.08, 0.045, 3, 2, logger);&lt;br /&gt;    double result = bp.CalculatePrice();&lt;br /&gt;&lt;br /&gt;    logger.Save(@"C:\BondPricerCalcs.xml");&lt;/pre&gt;&lt;p&gt;Will generate the following calculations log:&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false;"&gt;    &amp;lt;Results&amp;gt;&lt;br /&gt;      &amp;lt;Inputs&amp;gt;&lt;br /&gt;        &amp;lt;Input name="F" category="Inputs" value="100" /&amp;gt;&lt;br /&gt;        &amp;lt;Input name="C" category="Inputs" value="0.08" /&amp;gt;&lt;br /&gt;        &amp;lt;Input name="r" category="Inputs" value="0.045" /&amp;gt;&lt;br /&gt;        &amp;lt;Input name="T" category="Inputs" value="3" /&amp;gt;&lt;br /&gt;        &amp;lt;Input name="n" category="Inputs" value="2" /&amp;gt;&lt;br /&gt;      &amp;lt;/Inputs&amp;gt;&lt;br /&gt;      &amp;lt;SingleCalcs&amp;gt;&lt;br /&gt;        &amp;lt;SingleCalc name="m" category="CouponCalcs" formula="n.T" value="6" /&amp;gt;&lt;br /&gt;        &amp;lt;SingleCalc name="u" category="CouponCalcs" formula="(1 + r) ^ (1 / n)" value="1.0222524150130437" /&amp;gt;&lt;br /&gt;        &amp;lt;SingleCalc name="Sm" category="CouponCalcs" formula="Sum[t=1..m](C/u^t)" value="0.444727984347155" /&amp;gt;&lt;br /&gt;        &amp;lt;SingleCalc name="DF" category="ParCalcs" formula="F / (1+r)^T" value="87.629660405490938" /&amp;gt;&lt;br /&gt;        &amp;lt;SingleCalc name="Pc" category="Results" formula="Sm+DF" value="88.074388389838091" /&amp;gt;&lt;br /&gt;      &amp;lt;/SingleCalcs&amp;gt;&lt;br /&gt;      &amp;lt;IteratedCalcs&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="1" formula="C/u^t" value="0.078258558087122954" /&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="2" formula="C/u^t" value="0.076555023923444987" /&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="3" formula="C/u^t" value="0.07488857233217508" /&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="4" formula="C/u^t" value="0.0732583960989904" /&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="5" formula="C/u^t" value="0.071663705581028789" /&amp;gt;&lt;br /&gt;        &amp;lt;IteratedCalc name="S" category="CouponCalcs" iteration="6" formula="C/u^t" value="0.070103728324392739" /&amp;gt;&lt;br /&gt;      &amp;lt;/IteratedCalcs&amp;gt;&lt;br /&gt;    &amp;lt;/Results&amp;gt;&lt;/pre&gt;&lt;h4&gt;Generating the DGML markup&lt;/h4&gt;&lt;p&gt;The XML above contains all we need to create the nodes for our diagram. I considered using XSLT or hand crafting some C# to transform this into DGML, but then thought this is a great use for T4 templates – we just need to iterate over the elements in this XML document, and generate the corresponding DGML nodes.&lt;/p&gt;&lt;p&gt;In VS 2010 I add a new &lt;span style="font-family:Courier New;font-size:85%;"&gt;Text Template &lt;/span&gt;file to the solution and populate it as follows:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;&amp;lt;#@ template language="C#" #&amp;gt;&lt;br /&gt;&amp;lt;#@ output extension="dgml" #&amp;gt;&lt;br /&gt;&amp;lt;#@ assembly name="System.Core" #&amp;gt;&lt;br /&gt;&amp;lt;#@ assembly name="System.Xml" #&amp;gt;&lt;br /&gt;&amp;lt;#@ assembly name="System.Xml.Linq" #&amp;gt;&lt;br /&gt;&amp;lt;#@ import namespace="System.Linq" #&amp;gt;&lt;br /&gt;&amp;lt;#@ import namespace="System.Xml.Linq" #&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    var doc = XDocument.Load(@"C:\BondPricerCalcs.xml");&lt;br /&gt;#&amp;gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml"&amp;gt;&lt;br /&gt;  &amp;lt;Nodes&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    foreach (var element in doc.Element("Results").Element("Inputs").Descendants("Input"))&lt;br /&gt;    {&lt;br /&gt;        string name = element.Attribute("name").Value;&lt;br /&gt;        string category = element.Attribute("category").Value;&lt;br /&gt;        string value = element.Attribute("value").Value;&lt;br /&gt;#&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="&amp;lt;#= name #&amp;gt;" Category="&amp;lt;#= category #&amp;gt;" Description="&amp;lt;#= value #&amp;gt;" Label="&amp;lt;#= name #&amp;gt;" /&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    }&lt;br /&gt;#&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    foreach (var element in doc.Element("Results").Element("SingleCalcs").Descendants("SingleCalc"))&lt;br /&gt;    {&lt;br /&gt;        string name = element.Attribute("name").Value;&lt;br /&gt;        string category = element.Attribute("category").Value;&lt;br /&gt;        string formula = element.Attribute("formula").Value;&lt;br /&gt;        string value = element.Attribute("value").Value;&lt;br /&gt;#&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="&amp;lt;#= name #&amp;gt;" Category="&amp;lt;#= category #&amp;gt;" Description="&amp;lt;#= formula #&amp;gt; = &amp;lt;#= value #&amp;gt;" Label="&amp;lt;#= name #&amp;gt;" /&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    }&lt;br /&gt;#&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    foreach (var element in doc.Element("Results").Element("IteratedCalcs").Descendants("IteratedCalc"))&lt;br /&gt;    {&lt;br /&gt;        string name = element.Attribute("name").Value;&lt;br /&gt;        string category = element.Attribute("category").Value;&lt;br /&gt;        string iteration = element.Attribute("iteration").Value;&lt;br /&gt;        string formula = element.Attribute("formula").Value;&lt;br /&gt;        string value = element.Attribute("value").Value;&lt;br /&gt;#&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="&amp;lt;#= name #&amp;gt;&amp;lt;#= iteration #&amp;gt;" Category="&amp;lt;#= category #&amp;gt;" Description="&amp;lt;#= formula #&amp;gt;[&amp;lt;#= iteration #&amp;gt;] = &amp;lt;#= value #&amp;gt;" Label="&amp;lt;#= name #&amp;gt;[&amp;lt;#= iteration #&amp;gt;]" /&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    }&lt;br /&gt;#&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="Coupons" Category="CouponCalcs" Group="Expanded" Label="Coupons" /&amp;gt;&lt;br /&gt;  &amp;lt;/Nodes&amp;gt;&lt;br /&gt;  &amp;lt;Links&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="DF" Target="Pc" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="F" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="m" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="n" Target="m" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="n" Target="u" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="r" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="r" Target="u" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Sm" Target="Pc" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="T" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="T" Target="m" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="Sm" Category="Contains" /&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    var m = (from calc in doc.Element("Results").Element("SingleCalcs").Descendants("SingleCalc")&lt;br /&gt;             where calc.Attribute("name").Value == "m"&lt;br /&gt;             select int.Parse(calc.Attribute("value").Value)).First();&lt;br /&gt;    for(int t = 1; t &amp;lt;= m; t++)&lt;br /&gt;    {&lt;br /&gt;#&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S&amp;lt;#= t #&amp;gt;"/&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S&amp;lt;#= t #&amp;gt;"/&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S&amp;lt;#= t #&amp;gt;" Target="Sm"/&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S&amp;lt;#= t #&amp;gt;" Category="Contains" /&amp;gt;&lt;br /&gt;&amp;lt;#&lt;br /&gt;    }&lt;br /&gt;#&amp;gt;&lt;br /&gt;  &amp;lt;/Links&amp;gt;&lt;br /&gt;  &amp;lt;Categories&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Contains" Label="Contains" CanBeDataDriven="False" CanLinkedNodesBeDataDriven="True" IncomingActionLabel="Contained By" IsContainment="True" OutgoingActionLabel="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Inputs" Label="Inputs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="CouponCalcs" Label="Coupon Calcs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="ParCalcs" Label="Par Calcs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Results" Label="Results" IsTag="True" /&amp;gt;&lt;br /&gt;  &amp;lt;/Categories&amp;gt;&lt;br /&gt;  &amp;lt;Styles&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Coupon Calcs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('CouponCalcs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="#FFFFFF00" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Par Calcs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('ParCalcs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="Green" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Inputs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('Inputs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="White" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Results" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('Results')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="Blue" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;  &amp;lt;/Styles&amp;gt;&lt;br /&gt;&amp;lt;/DirectedGraph&amp;gt;&lt;/pre&gt;&lt;p&gt;So this basically iterates over the XML first to generate all the diagram nodes,  then adds all the static links (the ones which don’t change no matter what the model inputs are), and finally the links for the individual coupon calcs. Whenever this file is saved, it will generate a code-behind file as per the &lt;span style="font-family:Courier New;font-size:85%;"&gt;output &lt;/span&gt;directive, i.e. with a &lt;span style="font-family:Courier New;font-size:85%;"&gt;.dgml &lt;/span&gt;extension. If you open up this file, we see the DGML source:&lt;/p&gt;&lt;pre class="brush: xml; ruler: true; auto-links: false;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt;&amp;lt;DirectedGraph xmlns="http://schemas.microsoft.com/vs/2009/dgml"&amp;gt;&lt;br /&gt;  &amp;lt;Nodes&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="C" Category="Inputs" Description="0.08" Label="C" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="Coupons" Category="CouponCalcs" Group="Expanded" Label="Coupons" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="DF" Category="ParCalcs" Description="F / (1+r)^T = 87.629660405490938" Label="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="F" Category="Inputs" Description="100" Label="F" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="Pc" Category="Results" Description="Sm+DF = 88.074388389838091" Label="Pc" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S1" Category="CouponCalcs" Description="C/u^t[1] = 0.078258558087122954" Label="S[1]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S2" Category="CouponCalcs" Description="C/u^t[2] = 0.076555023923444987" Label="S[2]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S3" Category="CouponCalcs" Description="C/u^t[3] = 0.07488857233217508" Label="S[3]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S4" Category="CouponCalcs" Description="C/u^t[4] = 0.0732583960989904" Label="S[4]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S5" Category="CouponCalcs" Description="C/u^t[5] = 0.071663705581028789" Label="S[5]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="S6" Category="CouponCalcs" Description="C/u^t[6] = 0.070103728324392739" Label="S[6]" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="Sm" Category="CouponCalcs" Description="Sum[t=1..m](C/u^t) = 0.444727984347155" Label="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="T" Category="Inputs" Description="3" Label="T" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="m" Category="CouponCalcs" Description="n.T = 6" Label="m" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="n" Category="Inputs" Description="2" Label="n" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="r" Category="Inputs" Description="0.045" Label="r" /&amp;gt;&lt;br /&gt;    &amp;lt;Node Id="u" Category="CouponCalcs" Description="(1 + r) ^ (1 / n) = 1.0222524150130437" Label="u" /&amp;gt;&lt;br /&gt;  &amp;lt;/Nodes&amp;gt;&lt;br /&gt;  &amp;lt;Links&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S1" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S2" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S3" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S4" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S5" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="C" Target="S6" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S1" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S2" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S3" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S4" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S5" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="S6" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Coupons" Target="Sm" Category="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="DF" Target="Pc" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="F" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S1" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S2" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S3" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S4" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S5" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="S6" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="Sm" Target="Pc" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="T" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="T" Target="m" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="m" Target="Sm" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="n" Target="m" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="n" Target="u" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="r" Target="DF" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="r" Target="u" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S1" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S2" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S3" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S4" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S5" /&amp;gt;&lt;br /&gt;    &amp;lt;Link Source="u" Target="S6" /&amp;gt;&lt;br /&gt;  &amp;lt;/Links&amp;gt;&lt;br /&gt;  &amp;lt;Categories&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Contains" Label="Contains" CanBeDataDriven="False" CanLinkedNodesBeDataDriven="True" IncomingActionLabel="Contained By" IsContainment="True" OutgoingActionLabel="Contains" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="CouponCalcs" Label="Coupon Calcs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Inputs" Label="Inputs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="ParCalcs" Label="Par Calcs" IsTag="True" /&amp;gt;&lt;br /&gt;    &amp;lt;Category Id="Results" Label="Results" IsTag="True" /&amp;gt;&lt;br /&gt;  &amp;lt;/Categories&amp;gt;&lt;br /&gt;  &amp;lt;Properties&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="CanBeDataDriven" Label="CanBeDataDriven" Description="CanBeDataDriven" DataType="System.Boolean" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="CanLinkedNodesBeDataDriven" Label="CanLinkedNodesBeDataDriven" Description="CanLinkedNodesBeDataDriven" DataType="System.Boolean" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="Description" Label="Description" Description="Description" DataType="System.String" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="Group" Label="Group" Description="Display the node as a group" DataType="Microsoft.VisualStudio.Progression.GraphModel.GroupStyle" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="IncomingActionLabel" Label="IncomingActionLabel" Description="IncomingActionLabel" DataType="System.String" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="IsContainment" DataType="System.Boolean" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="IsTag" DataType="System.Boolean" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="Label" Label="Label" Description="Displayable label of an Annotatable object" DataType="System.String" /&amp;gt;&lt;br /&gt;    &amp;lt;Property Id="OutgoingActionLabel" Label="OutgoingActionLabel" Description="OutgoingActionLabel" DataType="System.String" /&amp;gt;&lt;br /&gt;  &amp;lt;/Properties&amp;gt;&lt;br /&gt;  &amp;lt;Styles&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Coupon Calcs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('CouponCalcs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="#FFFFFF00" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Par Calcs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('ParCalcs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="Green" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Inputs" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('Inputs')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="White" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;    &amp;lt;Style TargetType="Node" GroupLabel="Results" ValueLabel="Has category"&amp;gt;&lt;br /&gt;      &amp;lt;Condition Expression="HasCategory('Results')" /&amp;gt;&lt;br /&gt;      &amp;lt;Setter Property="Background" Value="Blue" /&amp;gt;&lt;br /&gt;    &amp;lt;/Style&amp;gt;&lt;br /&gt;  &amp;lt;/Styles&amp;gt;&lt;br /&gt;&amp;lt;/DirectedGraph&amp;gt;&lt;/pre&gt;&lt;p&gt;And we can also view the diagram. Note that we create a collapsible group for the iterated calculations, which could be hierarchical for very complicated models allowing you to visualise an entire set of calculations and drill down as required in order to investigate errors or inconsistencies.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_bqE0F2FFSYA/S7XkGPO2qxI/AAAAAAAAABM/FQ5lLmEzofg/s1600-h/Bondpricing4.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="Bond-pricing" border="0" alt="Bond-pricing" src="http://lh5.ggpht.com/_bqE0F2FFSYA/S7XkHTW-i9I/AAAAAAAAABY/i0jMmpCM1Fw/Bondpricing_thumb2.png?imgmax=800" width="640" height="464" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;h4&gt;Future Improvements&lt;/h4&gt;&lt;p&gt;There is a spillover of model-specific logic in the T4 template. With a bit of thought, we could should be able to create XML loggers which hold all the model specific logic, and related XML format and then generate a T4 template which is model agnostic.&lt;/p&gt;&lt;p&gt;We perform the calculations and logging separately. Instead, we could encode all calculations we perform as expression trees, and walk these trees to not only calculate the values, but also perform the logging (including automatically generating the string representations of each formula). This is way beyond the scope of this article, however.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-1919655231611614821?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/VfMyA6XATsU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/1919655231611614821/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=1919655231611614821" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1919655231611614821?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/1919655231611614821?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/VfMyA6XATsU/using-dgml-in-visual-studio-2010-to.html" title="Using DGML in Visual Studio 2010 to visualise a financial model" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_bqE0F2FFSYA/S7XkHTW-i9I/AAAAAAAAABY/i0jMmpCM1Fw/s72-c/Bondpricing_thumb2.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/02/using-dgml-in-visual-studio-2010-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIBQX06eSp7ImA9WxFTEkw.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-5819494707032716415</id><published>2010-02-08T20:00:00.000Z</published><updated>2010-04-02T14:05:50.311+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-02T14:05:50.311+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Rx" /><category scheme="http://www.blogger.com/atom/ns#" term="Twitter" /><title>A concrete example of a reactive application</title><content type="html">&lt;p&gt;Continuing on from my &lt;a href="http://blog.roundthecampfire.net/2010/02/06/A+Quick+Play+With+Reactive+Extensions+Rx.aspx"&gt;first play with the Rx framework&lt;/a&gt; yesterday, I thought it would be good to come up with a real world example. I thought about rss feeds and stock tickers, but in the end decided on an app with consumes the &lt;a href="http://apiwiki.twitter.com/Twitter-API-Documentation"&gt;Twitter REST API&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I will build up an application which can subscribe to a couple of twitter news feeds, polling for new messages on a particular schedule, and merging the results into a single output stream to which we subscribe.&lt;/p&gt;&lt;h5&gt;Accessing the Twitter API&lt;/h5&gt;&lt;p&gt;I am going to keep this very simple, just access the &lt;span style="font-family:Courier New;font-size:85%;"&gt;user_timeline&lt;/span&gt; service for a given user, and get the results in XML format, which make it easy for us to project into a &lt;span style="font-family:Courier New;font-size:85%;"&gt;Tweet&lt;/span&gt; class which we define. I create a class called &lt;span style="font-family:Courier New;font-size:85%;"&gt;TwitterAccess&lt;/span&gt; with one key &lt;span style="font-family:Courier New;font-size:85%;"&gt;static&lt;/span&gt; method:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;public static Tweet[] GetNewTweets(string username, long lastTweetId)&lt;br /&gt;{&lt;br /&gt;    if(lastTweetId &amp;lt; 1)&lt;br /&gt;        throw new ArgumentOutOfRangeException("lastTweetId", "id must be greater than 0");&lt;br /&gt;&lt;br /&gt;    string url = String.Format("http://twitter.com/statuses/user_timeline/{0}.xml?since_id={1}",&lt;br /&gt;                               username.Replace("@", ""), lastTweetId);&lt;br /&gt;    var doc = XDocument.Load(url);&lt;br /&gt;&lt;br /&gt;    var items = from s in doc.Descendants("status")&lt;br /&gt;                orderby long.Parse(s.Element("id").Value)&lt;br /&gt;                select new Tweet { Id = long.Parse(s.Element("id").Value),&lt;br /&gt;                                   Time = ParseTwitterDate(s.Element("created_at").Value),&lt;br /&gt;                                   Username = s.Element("user").Element("screen_name").Value,&lt;br /&gt;                                   Status = s.Element("text").Value };&lt;br /&gt;  &lt;br /&gt;    return items.ToArray();&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This method gets all tweets on the given users timeline whose ID is greater than &lt;span style="font-family:Courier New;font-size:85%;"&gt;lastTweetId&lt;/span&gt; (although the default limit in twitter is 20 tweets, you will need to specify the &lt;span style="font-family:Courier New;font-size:85%;"&gt;count&lt;/span&gt; parameter in the rest url if you need more, but this suits our purpose).&lt;/p&gt;&lt;p&gt;The &lt;span style="font-family:Courier New;font-size:85%;"&gt;Tweet&lt;/span&gt; class just wraps the properties you can see above, and the &lt;span style="font-family:Courier New;font-size:85%;"&gt;ParseTwitterDate&lt;/span&gt; method just does a &lt;span style="font-family:Courier New;font-size:85%;"&gt;DateTime.ParseExact&lt;/span&gt; for the specific date format used in twitter.&lt;/p&gt;&lt;h5&gt;Wrapping Twitter in an IObservable&amp;lt;T&amp;gt;&lt;/h5&gt;&lt;p&gt;Now that we have a means to access twitter, we should create a class which handles the polling of this service and pushes all new tweets out through an &lt;span style="font-family:Courier New;font-size:85%;"&gt;IObservable&amp;lt;Tweet&amp;gt;&lt;/span&gt; as follows:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;public class TweetStream&lt;br /&gt;{&lt;br /&gt;    private long lastTweet = 1;&lt;br /&gt;    private object updateLock = new object();&lt;br /&gt;    private IObservable&amp;lt;Tweet&amp;gt; stream;&lt;br /&gt;&lt;br /&gt;    public IObservable&amp;lt;Tweet&amp;gt; Stream&lt;br /&gt;    {&lt;br /&gt;        get { return stream; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public TweetStream(string username, int interval)&lt;br /&gt;    {&lt;br /&gt;        var xs = Observable.Interval(TimeSpan.FromSeconds(interval));&lt;br /&gt;        stream = xs.SelectMany(count =&amp;gt;&lt;br /&gt;            {&lt;br /&gt;                Tweet[] items;&lt;br /&gt;                lock (updateLock)&lt;br /&gt;                {&lt;br /&gt;                    items = TwitterAccess.GetNewTweets(username, lastTweet);&lt;br /&gt;                    lastTweet = items.Length &amp;gt; 0 ? items.Last().Id : lastTweet;&lt;br /&gt;                }&lt;br /&gt;                return items.ToObservable();&lt;br /&gt;            });&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;The &lt;span style="font-family:Courier New;font-size:85%;"&gt;SelectMany &lt;/span&gt;call allows us to define a function which is called each time the interval fires and which itself returns an &lt;span style="font-family:Courier New;font-size:85%;"&gt;IObservable&lt;/span&gt;. Note that we must use &lt;span style="font-family:Courier New;font-size:85%;"&gt;SelectMany &lt;/span&gt;instead of &lt;span style="font-family:Courier New;font-size:85%;"&gt;Select &lt;/span&gt;as &lt;span style="font-family:Courier New;font-size:85%;"&gt;SelectMany &lt;/span&gt;will automatically flatten all the items in the returned stream into its own stream of &lt;span style="font-family:Courier New;font-size:85%;"&gt;Tweets &lt;/span&gt;whereas &lt;span style="font-family:Courier New;font-size:85%;"&gt;Select &lt;/span&gt;would leave you with a stream of &lt;span style="font-family:Courier New;font-size:85%;"&gt;IObservables&lt;/span&gt;, which will then be difficult to handle.&lt;/p&gt;&lt;h5&gt;Getting some output from this stream&lt;/h5&gt;&lt;p&gt;I can now update the console app we looked at yesterday in order to create an instance of &lt;span style="font-family:Courier New;font-size:85%;"&gt;TweetStream&lt;/span&gt; and subscribe to its output, writing this in turn out to the console.&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;TweetStream bbc = new TweetStream("bbcnews", 120);&lt;br /&gt;&lt;br /&gt;var sub = bbc.Stream.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1}: {2}",&lt;br /&gt;                                i.Time.ToString("dd hh:mm"), i.Username, i.Status));&lt;/pre&gt;&lt;p&gt;Running this up we get the following output:&lt;/p&gt;&lt;pre&gt;&lt;span style="font-family:courier new;font-size:78%;color:#666666;"&gt;07 08:10: bbcnews: A man who was injured during a Premier League football match at Stoke City dies in hospital.  http://&lt;br /&gt;bit.ly/bDjtDM&lt;br /&gt;07 09:00: bbcnews: Worst snow storms to hit eastern US for decades  http://bit.ly/93Jpn9&lt;br /&gt;07 09:00: bbcnews: Iran's leader asks the country's nuclear chief to begin enriching uranium to 20%, in a new challenge&lt;br /&gt;to Western.. http://bit.ly/9AUplq&lt;br /&gt;...&lt;br /&gt;07 02:20: bbcnews: A Scottish pensioner becomes only the seventh person in history to achieve judo's highest rank. http:&lt;br /&gt;//bit.ly/8XRsxv&lt;br /&gt;07 02:40: bbcnews: Scotland take on France at Murrayfield in the third of the opening round of Six Nations fixtures. htt&lt;br /&gt;p://bit.ly/98KHLc&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;This is very cool – without much code we now have a live twitter feed from a single source, which will automatically bring in new tweets (if available) every two minutes. As a final exercise I will attempt to merge two twitter news feeds into one single stream.&lt;/p&gt;&lt;h5&gt;Merging Twitter Feeds&lt;/h5&gt;&lt;p&gt;It is a simple matter now to update the above code to create two input feeds and then merge them:&lt;/p&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;TweetStream bbc = new TweetStream("bbcnews", 120);&lt;br /&gt;TweetStream cnn = new TweetStream("cnn", 120);&lt;br /&gt;&lt;br /&gt;var news = bbc.Stream.Merge(cnn.Stream);&lt;br /&gt;&lt;br /&gt;var sub = news.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1}: {2}",&lt;br /&gt;                                i.Time.ToString("dd hh:mm"), i.Username, i.Status));&lt;/pre&gt;&lt;p&gt;Just by calling the &lt;span style="font-family:Courier New;font-size:85%;"&gt;Merge &lt;/span&gt;method, the output from the two streams gets combined into a single stream. Note that the tweets from a given stream remain in order, but the relative ordering between the two streams depends on how they are scheduled to execute, the merge doesn’t work based on the feed dates or Ids – this is left as an exercise for the reader.&lt;/p&gt;&lt;pre&gt;&lt;span style="font-family:courier new;font-size:78%;color:#666666;"&gt;07 12:00: bbcnews: England and Wales are drawn in the same qualifying group for Euro 2012 in Poland and the Ukraine. htt&lt;br /&gt;p://bit.ly/cCEza2&lt;br /&gt;07 12:00: bbcnews: Home Secretary Alan Johnson rejects the idea that MPs facing expenses charges might avoid trial by ci&lt;br /&gt;ting Parli.. http://bit.ly/9tk3X9&lt;br /&gt;...&lt;br /&gt;07 03:20: bbcnews: A court in Libya dismisses a case against a Swiss businessman who was accused of illegal business act&lt;br /&gt;ivities. http://bit.ly/da0kFc&lt;br /&gt;07 03:20: bbcnews: Police have launched an inquiry after a man's body was found on a main road in rural Stirlingshire. h&lt;br /&gt;ttp://bit.ly/9xHMGp&lt;br /&gt;06 01:06: CNN: Toyota: Apology but no new recall. http://on.cnn.com/cxQQrj&lt;br /&gt;06 01:31: CNN: All military health facilities get Plan B pill. http://on.cnn.com/dbrZox&lt;br /&gt;...&lt;br /&gt;06 11:26: CNN: Tonight 9 ET: Watch the Tea Party Convention's keynote address by Sarah Palin live on CNN, CNN.com and CN&lt;br /&gt;N's iPhone App.&lt;br /&gt;07 11:29: CNN: Residents shovel out from heavy snow as blizzard conditions sweep across the eastern U.S.: http://bit.ly/&lt;br /&gt;cFmAiU&lt;br /&gt;07 11:30: CNN: Steps turn into slopes:  http://bit.ly/cyVbMM&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-5819494707032716415?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/OybFXQtmQUM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/5819494707032716415/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=5819494707032716415" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/5819494707032716415?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/5819494707032716415?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/OybFXQtmQUM/concrete-example-of-reactive.html" title="A concrete example of a reactive application" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/02/concrete-example-of-reactive.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUAQHw9fSp7ImA9WxFQE08.&quot;"><id>tag:blogger.com,1999:blog-9069492732693164425.post-5152614475318175071</id><published>2010-02-07T20:00:00.005Z</published><updated>2010-05-08T13:54:01.265+01:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-05-08T13:54:01.265+01:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Rx" /><title>A quick play with Reactive Extensions (Rx)</title><content type="html">I have finally got around to taking a look at this &lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"&gt;very interesting framework&lt;/a&gt; by DevLabs at Microsoft. What it promises to do is amazing, namely to revolutionize certain types of event driven (i.e. asynchronous) applications by allowing to developer to use the familiar LINQ paradigm to manage multiple streams of incoming asynchronous events.&lt;br /&gt;
&lt;br /&gt;
There are already a fair number of videos about Rx available on Channel 9. In my opinion, &lt;a href="http://channel9.msdn.com/posts/Charles/Erik-Meijer-Rx-in-15-Minutes/"&gt;this Introduction by Erik Meijer&lt;/a&gt; is the best starting point, followed by &lt;a href="http://channel9.msdn.com/posts/J.Van.Gogh/Writing-your-first-Rx-Application/"&gt;Wes Dyer’s Hello World equivalent&lt;/a&gt;. Following these there are a number of In Depth videos, which are indexed on the &lt;a href="http://blogs.msdn.com/rxteam/archive/2009/12/16/reactive-extensions-api-in-depth-retry.aspx"&gt;Team Blog&lt;/a&gt;. I cannot hope to describe Rx and its API anywhere near as well as those guys, so for the rest of this post will assume you have at least skimmed through those intros.&lt;br /&gt;
&lt;h3&gt;Getting Started&lt;/h3&gt;For this quick test, I downloaded the &lt;a href="http://download.microsoft.com/download/6/2/A/62A3E195-254C-445A-8109-6AE77A28AB63/Rx_Net35_SP1.exe"&gt;.NET Framework 3.5 SP1 variant&lt;/a&gt; and installed it. The install goes to &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Program Files\Microsoft Reactive Extensions\Redist\DesktopV2&lt;/span&gt; and includes four assemblies and matching help files.&lt;br /&gt;
I crack open Visual Studio 2008 SP1 and create a new windows console application (oh yeah, we are pushing the boat out with this demonstration). Add references to the Rx framework assemblies:&lt;br /&gt;
&lt;h5 align="center"&gt;&lt;a href="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XoowfyKvI/AAAAAAAAABg/Emk50pPDRwg/s1600-h/Assemblies7.png"&gt;&lt;img alt="Assemblies" border="0" height="92" src="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XopVOQChI/AAAAAAAAABk/Kt09rYRkuVw/Assemblies_thumb5.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="Assemblies" width="192" /&gt;&lt;/a&gt;&lt;/h5&gt;&lt;h4&gt;Hello World&lt;/h4&gt;Lets just get straight in there and create a real hello world application using the Rx framework:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;" name="code"&gt;static void Main(string[] args)
{
    var xs = Observable.Return(&amp;quot;Hello world&amp;quot;);
    var sb = xs.Subscribe(msg =&amp;gt; Console.WriteLine(msg));

    Console.WriteLine(&amp;quot;Press any key to exit&amp;quot;);
    Console.ReadKey();

    sb.Dispose();
}&lt;/pre&gt;&lt;br /&gt;
In this trivial snippet, we call &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Observable.Return&lt;/span&gt; which creates an &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;IObservable&amp;lt;String&amp;gt;&lt;/span&gt; whose sole purpose is to push out a single string value and then terminate. In itself this would achieve nothing unless we create something which can subscribe to this stream, so we call &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Subscribe&lt;/span&gt; on this &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;IObservable&lt;/span&gt; and pass in a lambda which takes the message content (a string) and writes it to the console. So we get:&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_bqE0F2FFSYA/S7Xops_cNOI/AAAAAAAAABo/4WDOnG7jLVQ/s1600-h/HelloWorldoutput.png"&gt;&lt;img alt="HelloWorld-output" border="0" height="55" src="http://lh4.ggpht.com/_bqE0F2FFSYA/S7XoqPqGjaI/AAAAAAAAABs/OEZt-Xwhw48/HelloWorldoutput_thumb.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="HelloWorld-output" width="493" /&gt;&lt;/a&gt;&lt;/div&gt;This is a start, but is not exactly stretching the capabilities of Rx so far. Over the next few demos, hopefully we can start to see some of the real possibilities.&lt;br /&gt;
&lt;h4&gt;Counting&lt;/h4&gt;The above demo did one thing and then stopped. For real excitement, lets now create an &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;IObservable&lt;/span&gt; which just keeps pushing out events forever:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;var xs = Observable.Interval(TimeSpan.FromSeconds(1));
var sb = xs.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1}",
DateTime.Now.ToString("mm:ss"), i));&lt;/pre&gt;&lt;br /&gt;
The call to &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Observable.Interval&lt;/span&gt; gives us an &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;IObservable&lt;/span&gt; which will sit there pushing events continuously. It starts with an integer value of 0, and after each of the defined intervals it increments this and pushes it out again.&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XoqovjzUI/AAAAAAAAABw/bBGUhn5C04M/s1600-h/IncrementOneOutput%5B1%5D.png"&gt;&lt;img alt="IncrementOne-Output" border="0" height="106" src="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XorMTVh0I/AAAAAAAAAB0/nAQnfS9RM08/IncrementOneOutput_thumb.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="IncrementOne-Output" width="494" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
By itself this appears to be a relatively useless feature, but we will see later that in conjunction with some of the more advanced facilities offered by Rx, this can be quite powerful as a means to quantize some other stream of events.&lt;br /&gt;
&lt;h4&gt;Advanced Counting&lt;/h4&gt;For this section, lets first start by creating two separate streams of events with &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Observable.Interval&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;var xs = Observable.Interval(TimeSpan.FromSeconds(1));
var ys = Observable.Interval(TimeSpan.FromMilliseconds(200));

var sb1 = xs.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1} (xs)",
DateTime.Now.ToString("mm:ss"), i));
var sb2 = ys.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1} (ys)",
DateTime.Now.ToString("mm:ss"), i));&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XoruH_MbI/AAAAAAAAAB4/59rfOY_7jPc/s1600-h/IncrementTwoOutput.png"&gt;&lt;img alt="IncrementTwo-Output" border="0" height="183" src="http://lh4.ggpht.com/_bqE0F2FFSYA/S7XosHv2K1I/AAAAAAAAAB8/8yzXzvwctMg/IncrementTwoOutput_thumb.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="IncrementTwo-Output" width="494" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
As expected, we have two streams outputting results, one ticking five times faster than the other. If we want to synchronize these, we have two options, either throttle each stream so that we output a single event only when both streams have a new event available, or alternatively each time one of the streams pushes a new event we combine that with the most recent event of the other stream. These features are provided by the &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Zip&lt;/span&gt; and the &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;CombineLatest&lt;/span&gt; methods respectively.&lt;br /&gt;
&lt;h4&gt;Zipping Up&lt;/h4&gt;One of the nice touches in the videos linked above is the concept of marble diagrams. These do a very good job of visualizing some potentially mind-melting concurrency scenarios, and also do a good job in showing what each of the Rx operators achieve. The simple (no failures) scenario for &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Zip&lt;/span&gt; is as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XosvaPNSI/AAAAAAAAACA/DuplWqxKps8/s1600-h/ZipMarble6.png"&gt;&lt;img alt="Zip-Marble" border="0" height="221" src="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XotsiP08I/AAAAAAAAACE/YSmOgTbK0sM/ZipMarble_thumb4.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="Zip-Marble" width="569" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Each blob represents some event occurring with &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;xs&lt;/span&gt; and &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;ys&lt;/span&gt; being the input streams in this case. Stream &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;zs&lt;/span&gt; is created by zipping &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;xs&lt;/span&gt; with &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;ys&lt;/span&gt; and combining the two events using the function ‘&lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;f&lt;/span&gt;’.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;var xs = Observable.Interval(TimeSpan.FromSeconds(1));
var ys = Observable.Interval(TimeSpan.FromMilliseconds(200));
var zs = xs.Zip(ys, (x, y) =&amp;gt; String.Format("({0},{1})", x, y));

var sb = zs.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1} (zs)",
DateTime.Now.ToString("mm:ss"), i));&lt;/pre&gt;&lt;br /&gt;
In this method we introduce the call to &lt;span style="font-family: 'courier new'; font-size: 85%;"&gt;Zip&lt;/span&gt;, which combines events from the input streams, and created new events using the lambda. In this case we simply return a string representation of the tuple.&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_bqE0F2FFSYA/S7XotxMYIpI/AAAAAAAAACI/nP2ijmL0qJg/s1600-h/ZipOutput4.png"&gt;&lt;img alt="Zip-Output" border="0" height="116" src="http://lh4.ggpht.com/_bqE0F2FFSYA/S7XouXxdsuI/AAAAAAAAACM/RM3m3oFDFS4/ZipOutput_thumb2.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="Zip-Output" width="494" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
As we can see here, the 200ms stream is effectively throttled back to the speed of the slowest stream. In many cases this may be the desired result, but consider if the two streams were different types of financial market data, one remains up to date whilst the other gets more and more stale, after one hour of this, one of the streams would be feeding data 48 minutes old.&lt;br /&gt;
&lt;h4&gt;CombineLatest&lt;/h4&gt;So to solve this problem, another operator, CombineLatest, steps in. The marble diagram below shows that the same type of function is performed to pair the events, but the means for achieving this is quite different:&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_bqE0F2FFSYA/S7Xou7qDNiI/AAAAAAAAACQ/ulF4sHG_0fk/s1600-h/CombineLatestMarble4.png"&gt;&lt;img alt="CombineLatest-Marble" border="0" height="221" src="http://lh4.ggpht.com/_bqE0F2FFSYA/S7XovBmW2lI/AAAAAAAAACU/Axboi5rUqTo/CombineLatestMarble_thumb2.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="CombineLatest-Marble" width="569" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;
In this case, whenever we get an event on either stream, we combine that with the most recent event (or wait until there is one) on the other stream. So once we have data on both streams, the combined event stream pushes events as fast as the fastest of the input streams.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;&lt;pre class="brush: csharp; ruler: true; auto-links: false;"&gt;var xs = Observable.Interval(TimeSpan.FromSeconds(1));
var ys = Observable.Interval(TimeSpan.FromMilliseconds(200));
var zs = xs.CombineLatest(ys, (x, y) =&amp;gt; String.Format("({0},{1})", x, y));

var sb = zs.Subscribe(i =&amp;gt; Console.WriteLine("{0}: {1} (zs)",
DateTime.Now.ToString("mm:ss"), i));&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_bqE0F2FFSYA/S7XoviXCSLI/AAAAAAAAACY/hRVFS7EOH4g/s1600-h/CombineLatestOutput4.png"&gt;&lt;img alt="CombineLatest-Output" border="0" height="191" src="http://lh5.ggpht.com/_bqE0F2FFSYA/S7Xov_LIBwI/AAAAAAAAACc/cBk0GdgttD8/CombineLatestOutput_thumb2.png?imgmax=800" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="CombineLatest-Output" width="494" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;h3&gt;Summary&lt;/h3&gt;What I have briefly looked at is just the tip of the iceberg in terms of functionality. There are numerous other methods in the framework for dealing with events, and many ways in which they can be composed to achieve some very powerful results. Also, I have only looked at success scenarios so far, and Rx has much to give in terms of dealing with exceptions and retry policies on particular event streams.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9069492732693164425-5152614475318175071?l=blog.roundthecampfire.net' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RoundTheCampfire/~4/FY0a59g4nV8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.roundthecampfire.net/feeds/5152614475318175071/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=9069492732693164425&amp;postID=5152614475318175071" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/5152614475318175071?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9069492732693164425/posts/default/5152614475318175071?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/RoundTheCampfire/~3/FY0a59g4nV8/quick-play-with-reactive-extensions-rx.html" title="A quick play with Reactive Extensions (Rx)" /><author><name>Chris Ballard</name><uri>http://www.blogger.com/profile/14558028329429981215</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_bqE0F2FFSYA/S7XopVOQChI/AAAAAAAAABk/Kt09rYRkuVw/s72-c/Assemblies_thumb5.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.roundthecampfire.net/2010/02/quick-play-with-reactive-extensions-rx.html</feedburner:origLink></entry></feed>

