<?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:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en">
  <title type="text">Tim Robinson</title>
  <subtitle type="text" />

  <updated>2012-05-07T15:13:46Z</updated>
  <generator uri="http://blogofile.com/">Blogofile</generator>

  <link rel="alternate" type="text/html" href="http://www.partario.com/blog/" />
  <id>http://www.partario.com/blog//feed/atom/</id>
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/TimRobinson" /><feedburner:info uri="timrobinson" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[New NPackage binaries]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/WlouxvhqRf4/new-npackage-binaries.html" />
    <id>http://www.partario.com/blog/2010/05/new-npackage-binaries.html</id>
    <updated>2010-05-16T18:57:39Z</updated>
    <published>2010-05-16T18:57:39Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[New NPackage binaries]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/05/new-npackage-binaries.html">&lt;p id="p1"&gt;I've &lt;a href="http://sethgodin.typepad.com/seths_blog/2005/03/dont_shave_that.html"&gt;shaved two yaks&lt;/a&gt; this weekend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p id="p2"&gt;Ported the NPackage &lt;code&gt;install&lt;/code&gt; command to F#. There shouldn't be any visible change in the application: rather, F# lets me write more succinct code for handling HTTP and package dependencies. (Specifically, I was able to replace a lot of my boilerplace C# code with a &lt;a href="http://msdn.microsoft.com/en-us/library/dd233182.aspx"&gt;computation workflow&lt;/a&gt; that takes care of deciding which files need to be downloaded again and which ones can be left alone.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p3"&gt;Set up an instance of &lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; to take the source code from GitHub and build binaries for me. This isn't a version 1.0 release yet, but you're welcome to download the binaries and help me test them.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p4"&gt;&lt;strong&gt;&lt;a href="http://build.partario.com/guestAuth/repository/download/bt2/.lastSuccessful/NPackage.zip"&gt;Download the most recent NPackage binaries&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p id="p5"&gt;PS last week I promised I'd implement package dependencies. I haven't done that yet.&lt;/p&gt;
&lt;p id="p6"&gt;PPS here's another .NET packaging system to look out for: &lt;a href="http://strangelights.com/blog/archive/2010/05/16/1661.aspx"&gt;Sebastien Lambla's OpenWrap&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=WlouxvhqRf4:FlQv3iDi3rg:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=WlouxvhqRf4:FlQv3iDi3rg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=WlouxvhqRf4:FlQv3iDi3rg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=WlouxvhqRf4:FlQv3iDi3rg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=WlouxvhqRf4:FlQv3iDi3rg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=WlouxvhqRf4:FlQv3iDi3rg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/WlouxvhqRf4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/05/new-npackage-binaries.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[This week on NPackage]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/ItEvOxyy2ag/this-week-on-npackage.html" />
    <id>http://www.partario.com/blog/2010/05/this-week-on-npackage.html</id>
    <updated>2010-05-09T20:19:43Z</updated>
    <published>2010-05-09T20:19:43Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[This week on NPackage]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/05/this-week-on-npackage.html">&lt;p id="p1"&gt;&lt;a href="http://github.com/timrobinson/NPackage"&gt;Browse the NPackage source on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p id="p2"&gt;I implemented the local package database idea that I mentioned last weekend. Now the NPackage client downloads a &lt;a href="http://np.partario.com/packages.js"&gt;packages.js&lt;/a&gt; file that describes every version of every package; now you don't have to specify full package file URLs with version numbers. I've also switched to &lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; syntax for the package files, instead of using my hand-made Yaml-ish parser.&lt;/p&gt;
&lt;p id="p3"&gt;I want to do at least two more things before putting togther an NPackage version 1.0 release:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Packages should be able to depend on other packages. These dependencies should consist of a package name and, optionally, the range of version numbers that are acceptable. NPackage will pick the latest version of each package that satisfies all the version number constraints.&lt;/li&gt;
&lt;li&gt;Developers should be able to set up a local package repository that takes prececdence over the web site&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p4"&gt;Hopefully I'll at least have dependencies working by next weekend.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=ItEvOxyy2ag:s-62NKxhdbg:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=ItEvOxyy2ag:s-62NKxhdbg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=ItEvOxyy2ag:s-62NKxhdbg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=ItEvOxyy2ag:s-62NKxhdbg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=ItEvOxyy2ag:s-62NKxhdbg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=ItEvOxyy2ag:s-62NKxhdbg:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/ItEvOxyy2ag" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/05/this-week-on-npackage.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[First six NPackage packages]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/IK-FTAiC348/first.html" />
    <id>http://www.partario.com/blog/2010/05/first.html</id>
    <updated>2010-05-03T15:49:34Z</updated>
    <published>2010-05-03T15:49:34Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[First six NPackage packages]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/05/first.html">&lt;p id="p1"&gt;&lt;a href="http://github.com/timrobinson/NPackage"&gt;Browse the NPackage source on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p id="p2"&gt;This weekend I've had a couple of productive sessions on NPackage and I'm pretty happy with how it's working out.&lt;/p&gt;
&lt;p id="p3"&gt;I've set up package files on Amazon S3 for the following libraries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/log4net-1.2.10/log4net.np"&gt;log4net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/cecil-0.6/cecil.np"&gt;Mono Cecil&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/nhibernate-2.1.2/nhibernate.np"&gt;NHibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/nunit-2.5.5.10112/nunit.np"&gt;NUnit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/rhino.mocks-3.6/rhino.mocks.np"&gt;Rhino Mocks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://np.partario.com/sharpziplib-0.85.5/sharpziplib.np"&gt;SharpZipLib&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p4"&gt;These six packages test a few different scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NUnit and SharpZipLib are needed to build NPackage itself&lt;/li&gt;
&lt;li&gt;Rhino Mocks is a good test because the download URL doesn't resemble the name of the file that gets downloaded; I had to write code to parse the HTTP Content-Disposition header to make sense of it&lt;/li&gt;
&lt;li&gt;Cecil is an example of a library that's distributed with the rest of Mono, which is supplied as a large .tar.gz archive (the other libraries on the list above are all .zip files)&lt;/li&gt;
&lt;li&gt;NHibernate is an example of a library that has its own dependencies, i.e. log4net&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p5"&gt;Although NPackage is working nicely for its own development, I need to put in more work before the installation process is simple enough. Right now the &lt;a href="http://github.com/timrobinson/NPackage/blob/master/scripts/install"&gt;command to install NPackage's own dependencies&lt;/a&gt; looks like this:&lt;/p&gt;
&lt;div class="pygments_murphy"&gt;&lt;pre&gt;NPackage http://np.partario.com/nunit-2.5.5.10112/nunit.np \
         http://np.partario.com/sharpziplib-0.85.5/sharpziplib.np
&lt;/pre&gt;&lt;/div&gt;

&lt;p id="p6"&gt;I'd like to simplify it to this:&lt;/p&gt;
&lt;div class="pygments_murphy"&gt;&lt;pre&gt;np install nunit sharpziplib
&lt;/pre&gt;&lt;/div&gt;

&lt;p id="p7"&gt;To do this I'll need to handle dependencies properly. I expect I'll need to drop the approach of putting package descriptions in their own files: the client will need to contain enough intelligence to put together a dependency graph and install the right versions of the right packages. It will be easier to do this if the client can download a central package database list and make its decisions based on the descriptions within there.&lt;/p&gt;
&lt;p id="p8"&gt;I envisage having local databases that can contain a few local packages and delegate the rest to the central list on the web. I'd also like the client to be self-contained enough to carry on working even if this central package server falls over: the client should cache the most recent version of the list and work from there.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=IK-FTAiC348:8ZSTTDl1-KI:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=IK-FTAiC348:8ZSTTDl1-KI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=IK-FTAiC348:8ZSTTDl1-KI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=IK-FTAiC348:8ZSTTDl1-KI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=IK-FTAiC348:8ZSTTDl1-KI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=IK-FTAiC348:8ZSTTDl1-KI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/IK-FTAiC348" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/05/first.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[NPackage news]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/oKHy8ggMNzc/npackage-news.html" />
    <id>http://www.partario.com/blog/2010/04/npackage-news.html</id>
    <updated>2010-04-27T13:00:00Z</updated>
    <published>2010-04-27T13:00:00Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[NPackage news]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/04/npackage-news.html">&lt;p id="p1"&gt;I've had some time over the last couple of evenings to do some coding, so I've made a start on my package manager. So far I'm calling it &lt;strong&gt;NPackage&lt;/strong&gt;.&lt;/p&gt;
&lt;p id="p2"&gt;I defined a Yaml-format package file, containing the package name, description, version number; the name and email address of the maintainer; and an optional field for the URL of the download site. The package file then contains a list of libraries (i.e. .NET assembles) contributed by the package, with download URLs specified relative to the download site. &lt;/p&gt;
&lt;p id="p3"&gt;The idea behind making the download URL optional is that these package files can point to an existing download site for established libraries like NUnit. If the download URL is omitted then the NPackage client will look for binaries on the NPackage server, in the same location as the package file itself. A lot of libraries are going to be distributed in .zip files, so I was planning on having the NPackage client download these .zip files and unpack them into the layout dictated by the package file.&lt;/p&gt;
&lt;p id="p4"&gt;I'm using NPackage to develop NPackage, which means I had to hack together the parsing and download code myself without any unit testing framework or parsing library. Now that I've done that, I've hand-crafted a package file for NUnit (&lt;code&gt;nunit.np&lt;/code&gt;) that'll let me start writing unit tests.&lt;/p&gt;
&lt;p id="p5"&gt;There are a few areas I'm not sure about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I've started writing it in C#, but I'm tempted to switch to F#, at least for the core functionality. I'm expecting to need some strong dependency graph logic (for dependencies between packages and between files within a package), which will be easier to code in F#. However I'd like to be able to be able to build the sources on Mono, and I'm not aware of a standard way of invoking the F# compiler from a Mono build process.&lt;/li&gt;
&lt;li&gt;I'm only dealing with binary distribution for now (and &lt;a href="http://en.wikipedia.org/wiki/XCOPY_deployment"&gt;xcopy deployment&lt;/a&gt; at that). Building .NET libraries from source in a standard way could be tricky.&lt;/li&gt;
&lt;li&gt;I've picked a &lt;a href="http://en.wikipedia.org/wiki/Yaml"&gt;Yaml&lt;/a&gt;-based file format over XML because I expect these package files to be created by hand. As a result, it's going to be harder to generate or parse these files as part of an automated build system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p6"&gt;Here's the notes I made before I got started:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Find the package&lt;/li&gt;
&lt;li&gt;Package files like in cabal&lt;/li&gt;
&lt;li&gt;A couple of standard locations: Hackage-like web server, internal source control repository&lt;/li&gt;
&lt;li&gt;Package identified by: name and version&lt;/li&gt;
&lt;li&gt;Deal with variants (like: 2.0 vs 3.5 vs 4.0; 32-bit vs 64-bit) by having separate packages released at the same time&lt;/li&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Package files declare their own dependencies, cabal style&lt;/li&gt;
&lt;li&gt;Recursively fetch and install dependencies&lt;/li&gt;
&lt;li&gt;Download the code&lt;/li&gt;
&lt;li&gt;Package file specifies location of source code (default is src/ directory relative to package file)&lt;/li&gt;
&lt;li&gt;Packages can release binaries only, e.g. NUnit, log4net etc. get downloaded from their normal locations&lt;/li&gt;
&lt;li&gt;Support fetching from source control as well as HTTP? - may make sense for internal deployments, what about mixing matching SCC systems?&lt;/li&gt;
&lt;li&gt;Build the code&lt;/li&gt;
&lt;li&gt;Skip this if the package just has binaries&lt;/li&gt;
&lt;li&gt;Reference the binaries&lt;/li&gt;
&lt;li&gt;Update VS solution and project files&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=oKHy8ggMNzc:Vyw3eRY9Cgs:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=oKHy8ggMNzc:Vyw3eRY9Cgs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=oKHy8ggMNzc:Vyw3eRY9Cgs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=oKHy8ggMNzc:Vyw3eRY9Cgs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=oKHy8ggMNzc:Vyw3eRY9Cgs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=oKHy8ggMNzc:Vyw3eRY9Cgs:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/oKHy8ggMNzc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/04/npackage-news.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[.NET package manager feedback]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/dR674UD73HI/net-package-manager-feedback.html" />
    <id>http://www.partario.com/blog/2010/04/net-package-manager-feedback.html</id>
    <updated>2010-04-19T18:19:54Z</updated>
    <published>2010-04-19T18:19:54Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[.NET package manager feedback]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/04/net-package-manager-feedback.html">&lt;p id="p1"&gt;I don't seem to be the first one to be having problems keeping track of his .NET binaries:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://twitter.com/TheColonial/status/12416813543"&gt;OJ offered to build one&lt;/a&gt; :)&lt;/li&gt;
&lt;li&gt;John Mandia poined me towards several Java-based tools: &lt;a href="http://www.jfrog.org/products.php"&gt;Artifactory&lt;/a&gt;, &lt;a href="http://www.anthillpro.com/html/default.html"&gt;Antill Pro&lt;/a&gt; and &lt;a href="http://nexus.sonatype.org/"&gt;Nexus&lt;/a&gt;. Of these, Artifactory and Nexus are open source. Of course, Apache &lt;a href="http://maven.apache.org/"&gt;Maven&lt;/a&gt; is a fairly well-known Java packaging tool.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://twitter.com/jimmcslim/status/12417586016"&gt;James Webster showed me&lt;/a&gt; the &lt;a href="http://vsdm.codeplex.com/Wikipage"&gt;Visual Studio Dependencies Manager&lt;/a&gt;, an addin for Visual Studio 2003.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p2"&gt;Finally, &lt;a href="http://www.partario.com/blog/2010/04/can-i-have-a-net-package-manager.html#comment-39"&gt;Terry Spitz&lt;/a&gt; had some fairly enthusiastic feedback:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p id="p3"&gt;hell yes! we've got various vbscripts to do this. shouldn't it be 'easy' in say MSI (if too heavyweight), or powershell. additional points if it can handle multi-level caching, i.e. cross-region or internet code is cached on a team share as well as locally.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p id="p4"&gt;Windows Installer occurred to me when I started thinking about this. However, I think such a tool should be limited to deploying assemblies to a particular project's source tree -- deploying them via MSIs suggests putting them into a central location on each machine, and I predict that individual projects will start interfering with each other this way, particularly on a build server. On the other hand, Windows Installer does have the concept of &lt;a href="http://en.wikipedia.org/wiki/Merge_module"&gt;merge modules&lt;/a&gt;: mini MSIs for software components that get merged into the final application installer.&lt;/p&gt;
&lt;p id="p5"&gt;Terry's multi-level caching idea is nice. There should definitely be local team and Internet repositories. Additionally, geographically distributed teams probably want local caches to keep overhead to a minimum. And I noticed that my Amazon-based web server cleverly goes to a special Ubuntu package repository hosted on S3, which keeps things quick and hopefully reduces my bandwidth costs.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=dR674UD73HI:Jt0Iiuul8cs:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=dR674UD73HI:Jt0Iiuul8cs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=dR674UD73HI:Jt0Iiuul8cs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=dR674UD73HI:Jt0Iiuul8cs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=dR674UD73HI:Jt0Iiuul8cs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=dR674UD73HI:Jt0Iiuul8cs:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/dR674UD73HI" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/04/net-package-manager-feedback.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[Can I have a .NET package manager?]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/zsKovbC4GuE/can-i-have-a-net-package-manager.html" />
    <id>http://www.partario.com/blog/2010/04/can-i-have-a-net-package-manager.html</id>
    <updated>2010-04-18T20:28:29Z</updated>
    <published>2010-04-18T20:28:29Z</published>
    <category scheme="http://www.partario.com/blog/" term="NPackage" />
    <summary type="html"><![CDATA[Can I have a .NET package manager?]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/04/can-i-have-a-net-package-manager.html">&lt;p id="p1"&gt;Insipired by source code packaging systems like &lt;a href="http://www.haskell.org/cabal/"&gt;Haskell Cabal&lt;/a&gt;, I'd like a standard tool for publishing shared code. I've seen teams take a variety of sub-optimal approaches, including: building everything from source each time; building binaries once then referencing them from a network share; and building binaries then checking them into source control.&lt;/p&gt;
&lt;p id="p2"&gt;As a developer, what I'd like to be able to do is to declare the external libraries that my code depends on. I'd like it to work the same way for third-party code (say, NUnit and log4net) as for my own code (say, a library that gets re-used across several apps on the same team). There should be a standard format for publishing libraries, but there should be minimal effort involved in pulling one of these libraries into my code.&lt;/p&gt;
&lt;p id="p3"&gt;What I propose is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;One or more central package sites.&lt;/strong&gt; One could be a public web site that maintains a list of open-source libraries; teams could host their own for internal libraries. These internal sites could just be directories in the file system or in source control. Package sites just contain enough information to find the right binaries or source code -- the binaries and sources themselves don't have to live at the same site.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;command line app that updates packages to the current version,&lt;/strong&gt; either by downloading binaries or by downloading and building source code. This would run on individual developers' PCs and on a continuous integration server.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;tool for keeping Visual Studio project references up to date.&lt;/strong&gt; I spend far too much time in the Project References dialog -- or editing .csproj files by hand -- to fix broken reference paths and libraries accidentally referenced from a developer's GAC.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p4"&gt;I don't know of anything that solves the problem as cleanly as in other languages. Am I missing something?&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=zsKovbC4GuE:5QFnO5s7tLA:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=zsKovbC4GuE:5QFnO5s7tLA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=zsKovbC4GuE:5QFnO5s7tLA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=zsKovbC4GuE:5QFnO5s7tLA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=zsKovbC4GuE:5QFnO5s7tLA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=zsKovbC4GuE:5QFnO5s7tLA:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/zsKovbC4GuE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/04/can-i-have-a-net-package-manager.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[Movable Type on EC2]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/T720GJKEQGU/movable-type-on-ec2.html" />
    <id>http://www.partario.com/blog/2010/04/movable-type-on-ec2.html</id>
    <updated>2010-04-18T20:00:00Z</updated>
    <published>2010-04-18T20:00:00Z</published>
    <category scheme="http://www.partario.com/blog/" term="Uncategorized" />
    <summary type="html"><![CDATA[Movable Type on EC2]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/04/movable-type-on-ec2.html">&lt;p id="p1"&gt;I'm a big fan of virtual servers and I've always run this web site from one. Until recently I had it on a &lt;a href="http://www.partario.com/blog/2009/04/first-post.html"&gt;VMware instance on my home PC&lt;/a&gt;, although &lt;a href="http://www.partario.com/blog/2010/03/a-render-farm-in-haskell.html"&gt;my recent experience with Amazon EC2&lt;/a&gt; and a couple of large traffic spikes prompted me to move it.&lt;/p&gt;
&lt;p id="p2"&gt;In the end the process turned out to be pretty easy:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Back up to Amazon S3 using &lt;a href="http://duplicity.nongnu.org/"&gt;duplicity&lt;/a&gt;:&lt;/li&gt;
&lt;li&gt;MySQL dump: &lt;code&gt;mysqldump --all-databases&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;/etc/apache2&lt;/li&gt;
&lt;li&gt;/var/www&lt;/li&gt;
&lt;li&gt;Start an EC2 small instance running AMI Ubuntu 9.04 (ami-ccf615a5)&lt;/li&gt;
&lt;li&gt;Restore from Amazon S3&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apt-get -y install apache2 duplicity libapache2-mod-perl2 libdbd-mysql-perl libdbi-perl mysql-server perlmagick python-boto&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Restore MySQL dump, /etc/apache2 and /var/www using duplicity&lt;/li&gt;
&lt;li&gt;Run MySQL script against the local instance&lt;/li&gt;
&lt;li&gt;Start Apache. Check whether the static HTML pages and Movable Type's admin interface work.&lt;/li&gt;
&lt;li&gt;Assign an Amazon elastic IP address to the EC2 instance. This gives me a static IP address that I can refer to from DNS.&lt;/li&gt;
&lt;li&gt;Remap the DNS alias (an A record and a CNAME record) via my ISP's web site&lt;/li&gt;
&lt;li&gt;Done!&lt;/li&gt;
&lt;/ol&gt;
&lt;p id="p3"&gt;I'm happy with the changes so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performance has been fine: although publishing the site now takes 30 seconds not 15, I'm getting much better response times and bandwidth&lt;/li&gt;
&lt;li&gt;I'm paying to run an EC2 instance full time whereas before I was just paying for home power bills&lt;/li&gt;
&lt;li&gt;I'm not going to get shot by my ISP next time one of my posts appears on Reddit&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p4"&gt;The fact that I was taking daily backups made the move risk-free. It took a couple of attempts to get a working site on the EC2 server, but I was able to start a fresh instance and restore from backup each time. I also know that, if the site does fall over in future, restoring from backup will take a few minutes and I'll lose one day of data at most.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=T720GJKEQGU:I24ZyOFYMzs:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=T720GJKEQGU:I24ZyOFYMzs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=T720GJKEQGU:I24ZyOFYMzs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=T720GJKEQGU:I24ZyOFYMzs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=T720GJKEQGU:I24ZyOFYMzs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=T720GJKEQGU:I24ZyOFYMzs:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/T720GJKEQGU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/04/movable-type-on-ec2.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[Cherry Blossom in Jubilee Place]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/0wRueTsnYos/cherry-blossom-in-jubilee-place.html" />
    <id>http://www.partario.com/blog/2010/04/cherry-blossom-in-jubilee-place.html</id>
    <updated>2010-04-12T09:07:35Z</updated>
    <published>2010-04-12T09:07:35Z</published>
    <category scheme="http://www.partario.com/blog/" term="Uncategorized" />
    <summary type="html"><![CDATA[Cherry Blossom in Jubilee Place]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/04/cherry-blossom-in-jubilee-place.html">&lt;p id="p1"&gt;&lt;a href="http://www.flickr.com/photos/tim-robinson/4511725083/" title="photo sharing"&gt;&lt;img src="http://farm3.static.flickr.com/2168/4511725083_61ec2dc0c2_d.jpg" alt="" class="mt-image-none"/&gt;&lt;/a&gt;
&lt;br/&gt;
&lt;span style="font-size: 0.9em; margin-top: 0px;"&gt;
&lt;a href="http://www.flickr.com/photos/tim-robinson/4511725083/"&gt;Jubilee Place Cherry Blossom - 2&lt;/a&gt;
&lt;br/&gt;
Originally uploaded by &lt;a href="http://www.flickr.com/people/tim-robinson/"&gt;Tim Robinson&lt;/a&gt;
&lt;/span&gt;
&lt;p id="p2"&gt;Summer has almost arrived in London -- I took this at the weekend in one of the parks close to where I work.&lt;/p&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=0wRueTsnYos:2eDHuek8W2c:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=0wRueTsnYos:2eDHuek8W2c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=0wRueTsnYos:2eDHuek8W2c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=0wRueTsnYos:2eDHuek8W2c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=0wRueTsnYos:2eDHuek8W2c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=0wRueTsnYos:2eDHuek8W2c:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/0wRueTsnYos" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/04/cherry-blossom-in-jubilee-place.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[A render farm in Haskell]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/VjTQ92KFkhs/a-render-farm-in-haskell.html" />
    <id>http://www.partario.com/blog/2010/03/a-render-farm-in-haskell.html</id>
    <updated>2010-03-07T19:40:00Z</updated>
    <published>2010-03-07T19:40:00Z</published>
    <category scheme="http://www.partario.com/blog/" term="Uncategorized" />
    <summary type="html"><![CDATA[A render farm in Haskell]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2010/03/a-render-farm-in-haskell.html">&lt;p id="p1"&gt;&lt;a href="http://github.com/timrobinson/smallpt-haskell"&gt;Browse the full source of the ray tracer on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p id="p2"&gt;A few weeks back I came across the &lt;a href="http://kevinbeason.com/smallpt/"&gt;smallpt ray tracer&lt;/a&gt; by Kevin Beason. smallpt is a global illumination renderer written in 99 lines of C++. Since it uses a &lt;a href="http://en.wikipedia.org/wiki/Monte_Carlo_method"&gt;Monte Carlo&lt;/a&gt; technique to randomly cast rays and average the results, the longer you can leave it running, the better the image will look. Kevin's code uses OpenMP to split calculations across more than one CPU core.&lt;/p&gt;
&lt;p id="p3"&gt;&lt;a href="http://github.com/timrobinson/smallpt-haskell/raw/master/1024-768-4000spp.png"&gt;&lt;img alt="Sample smallpt image" src="http://www.partario.com/blog/2010/03/07/1024-768-4000spp.png" width="540" height="405" class="mt-image-none" style=""/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p id="p4"&gt;Since ray tracing is the sort of mathsy task that Haskell excels at, I wanted to see how what a Haskell port of Kevin's code looked like. That code itself isn't the subject of this article, because what I wanted to write about instead are the techniques you can use to distribute Haskell code across multiple cores. These techniques range from &lt;code&gt;parMap&lt;/code&gt; (which is almost transparent to the program, but provides little control over where the code runs) to brute-force distribution of work across several machines.&lt;/p&gt;
&lt;h3&gt;parMap&lt;/h3&gt;
&lt;p id="p5"&gt;One of the things I love about Haskell is that its pure functional nature makes it straightforward to parallelise code within a single machine. You can normally take any code implemented in terms of &lt;code&gt;map&lt;/code&gt; and parallelise it with &lt;code&gt;parMap&lt;/code&gt;, from the &lt;a href="http://hackage.haskell.org/packages/archive/parallel/latest/doc/html/Control-Parallel-Strategies.html"&gt;Control.Parallel.Strategies&lt;/a&gt; module. &lt;code&gt;parMap&lt;/code&gt; will use lightweight threads provided by the runtime to apply a function to each element in a list in parallel.&lt;/p&gt;
&lt;p id="p6"&gt;The &lt;code&gt;parMap&lt;/code&gt; function accepts an argument that controls the evaluation strategy. Most of the examples I've seen use &lt;code&gt;parMap rwhnf&lt;/code&gt; ("weak head normal form"), which only evaluates the outside of a data structure; the insides of your data are evaluated lazily, and this doesn't necessarily happen on one of the parallel lightweight threads as intended.&lt;/p&gt;
&lt;p id="p7"&gt;To evaluate anything more complicated than a list of simple values in you'll probably need to use &lt;code&gt;parMap rdeepseq&lt;/code&gt;, which recurses inside your data on the lightweight thread so that it's fully evaluated by the time &lt;code&gt;parMap&lt;/code&gt; finishes. &lt;code&gt;rdeepseq&lt;/code&gt; is defined in terms of the &lt;a href="http://hackage.haskell.org/packages/archive/deepseq/latest/doc/html/Control-DeepSeq.html"&gt;Control.DeepSeq&lt;/a&gt; module, and if you've defined your own types, you'll find you need to implement &lt;code&gt;NFData&lt;/code&gt;.&lt;/p&gt;
&lt;p id="p8"&gt;A final note on &lt;code&gt;parMap&lt;/code&gt;: don't forget to compile with the &lt;code&gt;-threaded&lt;/code&gt; flag, then run your program with &lt;code&gt;+RTS -Nx&lt;/code&gt;, where &lt;em&gt;x&lt;/em&gt; is the number of CPU cores you want to distribute across.&lt;/p&gt;
&lt;h3&gt;forkIO&lt;/h3&gt;
&lt;p id="p9"&gt;Haskell supports good old-fashioned manual concurrency with functions in the &lt;a href="http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Concurrent.html"&gt;Control.Concurrent&lt;/a&gt; module. This works broadly the same as in other languages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;forkIO&lt;/code&gt; to start an IO computation in parallel with the current thread&lt;/li&gt;
&lt;li&gt;Threads can communicate through objects called MVars: create a new one using &lt;code&gt;newEmptyMVar&lt;/code&gt; or &lt;code&gt;newMVar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;MVars can be empty, or they can hold at most one value:&lt;/li&gt;
&lt;li&gt;Read a value from an MVar using &lt;code&gt;takeMVar&lt;/code&gt;. This will block if the MVar is currently empty.&lt;/li&gt;
&lt;li&gt;Write a value to an MVar using &lt;code&gt;putMVar&lt;/code&gt;. This will block if the MVar is currently full. Calling &lt;code&gt;putMVar&lt;/code&gt; wakes up one of the threads that's blocked inside &lt;code&gt;takeMVar&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p10"&gt;&lt;code&gt;forkIO&lt;/code&gt; starts a computation in parallel and lets you essentially forget about it; mvars are an effective way of encapsulating mutable state shared between more than one thread. What I like about this is that there's no error-prone manual locking like you'd find in, say, Java or .NET. Although &lt;code&gt;forkIO&lt;/code&gt; and mvars give you full control over thread scheduling, they're not drop-in replacements for sequential calculations in the same way as &lt;code&gt;parMap&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Brute force&lt;/h3&gt;
&lt;p id="p11"&gt;The previous two techniques rely on the multi-threading capabilities of the Haskell runtime. They know nothing of what's happening outside of a single Haskell process, which limits them to the number of cores present in the machine. To go beyond that, separate instances of your program will need to communicate with each other over a network.&lt;/p&gt;
&lt;p id="p12"&gt;In my Haskell port of smallpt, I used this technique to run as many instances of the program as needed: one process per core on the local machine, and one process on each of a range of instances running on Amazon EC2. The communication protocol is as simple as possible: plain text over pipes. I used &lt;code&gt;ssh&lt;/code&gt; to communicate with the EC2 instances, so from the outside there's no difference between a local instance and one running on the cloud.&lt;/p&gt;
&lt;p id="p13"&gt;&lt;a href="http://github.com/timrobinson/smallpt-haskell/blob/master/Tim/Smallpt/Distribution.hs"&gt;The algorithm&lt;/a&gt; goes as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Establish the work you need to do. In this case, a work item is one line in the final rendered image.&lt;/li&gt;
&lt;li&gt;Split the work into tasks you can give to the worker processes. For simplicity, I'm splitting the work equally to give one task to each worker.&lt;/li&gt;
&lt;li&gt;Launch the workers and provide them with the task inputs. Since workers accept plain text, I take a &lt;code&gt;Work&lt;/code&gt; object and &lt;code&gt;hPrint&lt;/code&gt; it to a pipe.&lt;/li&gt;
&lt;li&gt;When each worker finishes, collect its output. Outputs will come back in an unpredictable order.&lt;/li&gt;
&lt;li&gt;When all the workers are done, sort all of the outputs into the same order as the inputs&lt;/li&gt;
&lt;/ol&gt;
&lt;p id="p14"&gt;The coordinator is the program you launch from the command line, and it deals with things like command-line parsing, executing the distribution algorithm above, and writing a .png format image at the end. The worker processes are themselves instances of the &lt;code&gt;smallpt&lt;/code&gt; executable, launched with the &lt;code&gt;-r&lt;/code&gt; flag. In effect what each &lt;code&gt;smallpt -r&lt;/code&gt; does is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- Render one line of the scene and return it as a list of pixels
line :: (Floating a, Ord a, Random a) =&amp;gt; Context a -&amp;gt; Int -&amp;gt; [Vec a]

runWorker = interact (show . map line . read)
&lt;/code&gt;&lt;/pre&gt;
&lt;p id="p15"&gt;One potential flaw in this is that, because you're communicating over plain text, the Haskell type system won't trap any errors: there isn't necessarily any link between the types in the coordinator and the types in the worker. The interface to the distribution code consists of a &lt;code&gt;Coordinator a b&lt;/code&gt; record, where &lt;code&gt;a&lt;/code&gt; is the type for inputs to the workers, and &lt;code&gt;b&lt;/code&gt; is the type that the workers produce as output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data (Show a, Read b) =&amp;gt; Coordinator a b = 
    Coordinator { submitWork :: [String] -&amp;gt; [a] -&amp;gt; IO [b],
                  runWorker :: IO () }

coordinator :: (Read a, Show a, Read b, Show b) =&amp;gt; (a -&amp;gt; b) -&amp;gt; Coordinator a b
coordinator worker = 
    Coordinator { submitWork = submitWork',
                  runWorker = interact (show . map worker . read) }
&lt;/code&gt;&lt;/pre&gt;
&lt;p id="p16"&gt;Most of the multi-threading code lives inside the &lt;code&gt;submitWork'&lt;/code&gt; function which implements the algorithm above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Given a list of worker commands lines (&lt;code&gt;[String]&lt;/code&gt;) and the work itself (&lt;code&gt;[a]&lt;/code&gt;), produce a list of tuples of workers and tasks&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;forkIO&lt;/code&gt;, fork one thread per worker. Inside each of these threads:&lt;/li&gt;
&lt;li&gt;Start the worker process itself (via &lt;code&gt;createProcess shell&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Write an &lt;code&gt;[a]&lt;/code&gt; to its standard input&lt;/li&gt;
&lt;li&gt;Read a &lt;code&gt;[b]&lt;/code&gt; from its standard output&lt;/li&gt;
&lt;li&gt;Put the &lt;code&gt;[b]&lt;/code&gt; into an mvar shared between all worker threads&lt;/li&gt;
&lt;li&gt;Back in the coordinator thread, call &lt;code&gt;takeMVar&lt;/code&gt; once for each worker. This produces a list of results as a &lt;code&gt;[[b]]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once all the workers have finished, collapse the results into a &lt;code&gt;[b]&lt;/code&gt;, making sure the output list comes back in the same order as the original inputs. If any of the workers encountered an error, use &lt;code&gt;ioError&lt;/code&gt; to fail the whole operation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p id="p17"&gt;This approach works remarkably well for this simple ray tracer demo. But it has some serious flaws that you'd want to avoid in a production system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Any failed worker process invalidates the whole set of results. Even in the absence of software bugs, machines can fail any time (consider how often disks fail when you've got 4,000 of them). The coordinator should recognise transient errors and retry those tasks; it might choose to take workers out of rotation if they fail repeatedly.&lt;/li&gt;
&lt;li&gt;All machines are assumed to be equally powerful. This is rarely the case: for instance, workers running on my Mac here finish far sooner than ones on my small Amazon instances.&lt;/li&gt;
&lt;li&gt;All work is assumed to take the same length of time to complete. Even in this simple ray tracer, plain diffuse surfaces are much easier to calculate than reflective (shiny) ones or refractive (transparent) ones.&lt;/li&gt;
&lt;li&gt;Tasks are allocated up front. If a worker finishes early -- maybe because it's running on a Mac Pro, or because it generated a line of empty space -- it can't have any more work allocated to it.&lt;/li&gt;
&lt;li&gt;Workers can't spawn other workers. In my code the worker function isn't declared in the IO monad, so it can't interact with anything. Even if it could, it would need to know about all of the other workers so that it could pick an idle core to do work on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p18"&gt;Next time I'll talk about some of the code in the ray tracer itself, as well as some approaches you'd use in practice to correct these flaws in the demo.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=VjTQ92KFkhs:Vc02cG194Rk:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=VjTQ92KFkhs:Vc02cG194Rk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=VjTQ92KFkhs:Vc02cG194Rk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=VjTQ92KFkhs:Vc02cG194Rk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=VjTQ92KFkhs:Vc02cG194Rk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=VjTQ92KFkhs:Vc02cG194Rk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/VjTQ92KFkhs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2010/03/a-render-farm-in-haskell.html</feedburner:origLink></entry>
  <entry>
    <author>
      <name />
      <uri>http://www.partario.com/blog/</uri>
    </author>
    <title type="html"><![CDATA[An improved spelling corrector in Haskell]]></title>
    <link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/TimRobinson/~3/5NkAOFVxEu4/an-improved-spelling-corrector-in-haskell.html" />
    <id>http://www.partario.com/blog/2009/11/an-improved-spelling-corrector-in-haskell.html</id>
    <updated>2009-11-01T11:09:54Z</updated>
    <published>2009-11-01T11:09:54Z</published>
    <category scheme="http://www.partario.com/blog/" term="Uncategorized" />
    <summary type="html"><![CDATA[An improved spelling corrector in Haskell]]></summary>
    <content type="html" xml:base="http://www.partario.com/blog/2009/11/an-improved-spelling-corrector-in-haskell.html">&lt;p id="p1"&gt;&lt;a href="http://www.partario.com/blog/2009/10/a-spelling-corrector-in-haskell.html"&gt;My previous post&lt;/a&gt; came up on the &lt;a href="http://www.reddit.com/r/haskell/comments/9zowr/a_spelling_corrector_in_haskell/"&gt;Haskell Reddit&lt;/a&gt; yesterday, and I got some great suggestions for improvements to the program, which &lt;a href="http://github.com/timrobinson/spell-correct/blob/master/Correct.hs"&gt;I've checked into GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p id="p2"&gt;&lt;code&gt;Map.fromListWith&lt;/code&gt; replaces &lt;code&gt;List.foldl'&lt;/code&gt; and &lt;code&gt;Map.insertWith'&lt;/code&gt;. &lt;a href="http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.html#v%3AfromListWith"&gt;&lt;code&gt;fromListWith&lt;/code&gt;&lt;/a&gt; appears to be specifically designed for aggregating values that share a common key (in .NET terminology it's the &lt;a href="http://msdn.microsoft.com/en-us/library/bb534501.aspx"&gt;&lt;code&gt;GroupBy&lt;/code&gt;&lt;/a&gt; function).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p3"&gt;I'll commonly use a construct like &lt;code&gt;readFile "big.txt" &amp;gt;&amp;gt;= return . train . lowerWords&lt;/code&gt;, to bind a monad value &lt;code&gt;readFile "big.txt"&lt;/code&gt; to a function &lt;code&gt;(train . lowerWords)&lt;/code&gt;, then produce a new monad value with &lt;code&gt;return&lt;/code&gt;. A shorter way to write this is &lt;code&gt;fmap (train . lowerWords) (readFile "big.txt")&lt;/code&gt;, or, with an import from Control.Applicative, &lt;code&gt;(train . lowerWords &amp;lt;$&amp;gt; readFile "big.txt")&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p id="p4"&gt;You can replace the lambda syntax &lt;code&gt;(\w -&amp;gt; Map.lookup w nwords)&lt;/code&gt; with an operator section, &lt;code&gt;('Map.lookup' nwords)&lt;/code&gt;. You might see this more commonly as &lt;code&gt;(+1)&lt;/code&gt; in place of &lt;code&gt;(\x -&amp;gt; x + 1)&lt;/code&gt;; it's the same thing. &lt;strong class="alt"&gt;Edit:&lt;/strong&gt; the challenging Markdown syntax means that you'll have to imagine the single quotes around &lt;code&gt;Map.lookup&lt;/code&gt; replaced with backticks, `.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p5"&gt;I should have realised this at the time, but it didn't occur to me that &lt;a href="http://www.haskell.org/onlinereport/exps.html#list-comprehensions"&gt;you can use full pattern-matching syntax in the right-hand side of a Haskell list comprehension&lt;/a&gt;. If the match fails on some element then that element is filtered out. We can use this to improve on the Python version of the &lt;code&gt;edits1&lt;/code&gt; function: whereas the Python version combines its &lt;code&gt;b[0]&lt;/code&gt; subscripts with an &lt;code&gt;if b&lt;/code&gt; check, the Haskell version can use pattern matching to do both. We can also use the &lt;code&gt;inits&lt;/code&gt; and &lt;code&gt;tails&lt;/code&gt; functions to build substrings instead of brute-force applications of &lt;code&gt;take&lt;/code&gt; and &lt;code&gt;drop&lt;/code&gt;.&lt;/p&gt;
&lt;div class="pygments_murphy"&gt;&lt;pre&gt;# Python
def edits1(word):
   s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
   deletes    = [a + b[1:] for a, b in s if b]
   transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)&amp;gt;1]
   replaces   = [a + c + b[1:] for a, b in s for c in alphabet if b]
   inserts    = [a + c + b     for a, b in s for c in alphabet]
   return set(deletes + transposes + replaces + inserts)

&amp;gt; -- Haskell
&amp;gt; edits1 word = let s = zip (inits word) (tails word)
&amp;gt;                   deletes    = [ a ++ y     | (a, _:y  ) &amp;lt;- s ]
&amp;gt;                   transposes = [ a ++ y:x:z | (a, x:y:z) &amp;lt;- s ]
&amp;gt;                   replaces   = [ a ++ c:y   | (a, _:y  ) &amp;lt;- s, c &amp;lt;- alphabet ]
&amp;gt;                   inserts    = [ a ++ c:x   | (a, x    ) &amp;lt;- s, c &amp;lt;- alphabet ]
&amp;gt;                in Set.fromList $ concat [ deletes, transposes, replaces, inserts ]
&lt;/pre&gt;&lt;/div&gt;

&lt;p id="p6"&gt;The &lt;code&gt;edits1&lt;/code&gt; function is the densest one in both the Python and Haskell versions. It's the one where the intent of the code was least clear to me when I originally saw it, probably because of the extra clutter in the list comprehensions. In the latest Haskell revision it's more obvious what's going on.&lt;/p&gt;
&lt;p id="p7"&gt;I've consistently used the names &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; for the first three parts of the word's suffix. Because they consistently stand for the same thing, any inconsistencies jump out at you when you read the code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;a ++ y&lt;/code&gt; stands out because &lt;code&gt;x&lt;/code&gt; is missing; it's been &lt;em&gt;deleted&lt;/em&gt;. (&lt;code&gt;x&lt;/code&gt; isn't even mentioned in the pattern match.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a ++ y:x:z&lt;/code&gt; stands out because &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are the wrong way round; we're &lt;em&gt;transposing&lt;/em&gt; them&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a ++ c:y&lt;/code&gt; stands out because we've got &lt;code&gt;c&lt;/code&gt; instead of &lt;code&gt;x&lt;/code&gt;; &lt;code&gt;x&lt;/code&gt; has been &lt;em&gt;replaced&lt;/em&gt;. (Again, &lt;code&gt;x&lt;/code&gt; has dropped out of the pattern match.)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;a ++ c:x&lt;/code&gt; has &lt;code&gt;c&lt;/code&gt; in front of &lt;code&gt;x&lt;/code&gt;; it's been &lt;em&gt;inserted&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p id="p8"&gt;After I'd written the first Haskell version I was skeptical. The Python version uses some typical Python idioms, like &lt;code&gt;if b&lt;/code&gt; for checking for empty strings, using the same syntax for accessing lists and sets, and overloading the &lt;code&gt;or&lt;/code&gt; operator to look for the first non-empty set, and Haskell doesn't have these same shortcuts. However the latest set of revisions makes the the core algorithm in the Haskell version more readable than the Python equivalent.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=5NkAOFVxEu4:8fJ5F0pYhzY:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=5NkAOFVxEu4:8fJ5F0pYhzY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=5NkAOFVxEu4:8fJ5F0pYhzY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=5NkAOFVxEu4:8fJ5F0pYhzY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?i=5NkAOFVxEu4:8fJ5F0pYhzY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/TimRobinson?a=5NkAOFVxEu4:8fJ5F0pYhzY:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/TimRobinson?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/TimRobinson/~4/5NkAOFVxEu4" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.partario.com/blog/2009/11/an-improved-spelling-corrector-in-haskell.html</feedburner:origLink></entry>
</feed>
