<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Random Hacks: Tag Haskell</title>
    <link>http://www.randomhacks.net/articles/tag/Haskell?tag=Haskell</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>Ubiquitous Hoogle</title>
      <description>&lt;p&gt;&lt;a href="https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_User_Tutorial"&gt;Ubiquity&lt;/a&gt; is an experimental Firefox plugin. It&amp;#8217;s a &amp;#8220;graphical command line&amp;#8221; similar to &lt;a href="http://en.wikipedia.org/wiki/Quicksilver_" title="software"&gt;QuickSilver&lt;/a&gt; on the Macintosh.&lt;/p&gt;

&lt;p&gt;You can easily add your own commands to Ubiquity. The following article shows how to create a &lt;a href="http://www.haskell.org/hoogle/"&gt;Hoogle&lt;/a&gt; search command that looks up &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt; functions by name or by type signature.&lt;/p&gt;

&lt;p&gt;&lt;img src="/files/ubiq-hoogle-putStr.png" width="534" height="407" alt="Searching for putStr" /&gt;&lt;/p&gt;

&lt;p&gt;You can press &lt;strong&gt;Return&lt;/strong&gt; or click on one the links in the preview.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2008/09/01/ubiquitous-hoogle"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 01 Sep 2008 10:33:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:9f156248-1302-4cdc-9755-3007955a2677</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2008/09/01/ubiquitous-hoogle</link>
      <category>Haskell</category>
      <category>JavaScript</category>
      <category>Firefox</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/581</trackback:ping>
    </item>
    <item>
      <title>Probability monads at Hac 07 II</title>
      <description>&lt;p&gt;From October 5-7, I&amp;#8217;ll be at the &lt;a href="http://www.haskell.org/haskellwiki/Hac_2007_II"&gt;Haskell Hackathon in Freiburg&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll be working on probability monads, attempting to turn my &lt;a href="http://www.randomhacks.net/articles/2007/04/19/robot-localization-particle-system-monad"&gt;various blog articles&lt;/a&gt; into a real Haskell library.&lt;/p&gt;

&lt;p&gt;Some resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.randomhacks.net/darcs/probability/"&gt;Control.Monad.Probability source code&lt;/a&gt;: This is the as-yet-unreconstructed code from my blog posts.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.randomhacks.net/darcs/probability-monads/probability-monads.pdf"&gt;Draft paper on probability monads&lt;/a&gt;: This paper explains the theory, and it has terser implementations of some ideas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you were a peer reviewer, or gave me feedback on the paper, my humble thanks&amp;#8211;and apologies. I haven&amp;#8217;t had a chance to revise the paper yet, and so your feedback is not yet included.&lt;/p&gt;

&lt;p&gt;See you at the Hackathon!&lt;/p&gt;</description>
      <pubDate>Tue, 02 Oct 2007 07:50:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:1603ed79-bdc5-4bf1-aafd-33c8c29bb6de</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/10/02/probability-monads-at-hac-07-ii</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <category>Probability</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/509</trackback:ping>
    </item>
    <item>
      <title>Freiburg in October: Scheme, Dylan, and probability monads</title>
      <description>&lt;p&gt;Good morning! I&amp;#8217;ll be in Freiburg for several events this October, including &lt;a href="http://cufp.galois.com/"&gt;CUFP&lt;/a&gt; and the &lt;a href="http://haskell.org/haskellwiki/Hac_2007_II"&gt;Haskell Hackathon&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Commercial Users of Functional Programming (CUFP)&lt;/h4&gt;

&lt;p&gt;On October 4th, I&amp;#8217;ll be speaking at &lt;a href="http://cufp.galois.com/"&gt;CUFP &amp;rsquo;07&lt;/a&gt;, describing the use of Scheme in a real-world multimedia engine. Some likely topics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How we switched to Scheme (and why refactoring is your friend).&lt;/li&gt;
&lt;li&gt;How our artists learned to program in Scheme (it&amp;#8217;s all about the tools).&lt;/li&gt;
&lt;li&gt;The tension between functional programming and objects: Can we have both?&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Dylan Beer Night&lt;/h4&gt;

&lt;p&gt;Once upon a time, I dreamt of &lt;a href="http://www.cs.dartmouth.edu/reports/abstracts/TR2001-404/"&gt;generic functions&lt;/a&gt; and built RPMs for &lt;a href="http://web.archive.org/web/19990125095755/http://www.gwydiondylan.org/"&gt;Gwydion Dylan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some current and former Dylan hackers are hoping to meet in Freiburg, most likely on October 4th. If you&amp;#8217;re at ICFP or one of the workshops, we&amp;#8217;d love to hear from you.&lt;/p&gt;

&lt;h4&gt;Haskell Hackathon&lt;/h4&gt;

&lt;p&gt;I&amp;#8217;ll be at the &lt;a href="http://haskell.org/haskellwiki/Hac_2007_II"&gt;Haskell Hackathon&lt;/a&gt; from Friday to Sunday.&lt;/p&gt;

&lt;p&gt;Perhaps it&amp;#8217;s time to whip &lt;a href="http://www.randomhacks.net/darcs/probability/"&gt;Control.Monad.Probability&lt;/a&gt; into shape?&lt;/p&gt;</description>
      <pubDate>Tue, 18 Sep 2007 12:36:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:b660e303-82af-41f0-8576-ad58b8fb8cc0</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/09/18/freiburg-in-october</link>
      <category>Scheme</category>
      <category>Dylan</category>
      <category>Haskell</category>
      <category>Monads</category>
      <category>Probability</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/506</trackback:ping>
    </item>
    <item>
      <title>Bowling in Haskell: A response to Ron Jeffries</title>
      <description>&lt;p&gt;Bowling is a &lt;a href="http://en.wikipedia.org/wiki/Ten-pin_bowling#Scoring"&gt;tricky game to score&lt;/a&gt;.  It&amp;#8217;s just complicated enough
to act as a good programming exercise.  And Ron Jeffries has performed this
exercise many times, in &lt;a href="http://www.xprogramming.com/xpmag/acsBowling.htm" title="Adventures in C#: The Bowling Game"&gt;C#&lt;/a&gt;, &lt;a href="http://www.xprogramming.com/xpmag/BowlingForSmalltalkII.htm" title="DBC: Bowling For Smalltalk II"&gt;Smalltalk&lt;/a&gt;, and &lt;a href="http://www.google.com/search?q=+site:www.xprogramming.com+jeffries+bowling" title="More bowling"&gt;other
languages&lt;/a&gt;.  He&amp;#8217;s been searching for a tidy and elegant solution, one
which makes the rules of bowling as clear as possible.&lt;/p&gt;

&lt;p&gt;In the past, though, Jeffries has been a bit skeptical of &lt;a href="http://www.xprogramming.com/xpmag/dbcHaskellBowling.htm" title="Haskell Bowling"&gt;Haskell
implementations of bowling&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;The recursive [Haskell] solution, however, is questionable on
more fundamental grounds. A game of bowling consists of ten frames, not
less or more, and the &amp;#8220;ten-ness&amp;#8221; of the game is not represented in the
recursive solutions at all. Even if we let that slide, the recursive
solutions make it a bit hard to understand what&amp;#8217;s going on.&lt;/blockquote&gt;

&lt;p&gt;Let&amp;#8217;s see if we can do better.  No knowledge of bowling is required&amp;#8211;if we
do this right, our program should be at least as clear as an
&lt;a href="http://en.wikipedia.org/wiki/Ten-pin_bowling#Scoring"&gt;English-language version of the rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Along the way, we&amp;#8217;ll encounter lazy lists, an interesting recursion combinator, and &lt;a href="http://www.haskell.org/hoogle/"&gt;Hoogle&lt;/a&gt;, the Haskell search engine.&lt;/p&gt;

&lt;h3&gt;The rules of bowling&lt;/h3&gt;

&lt;p&gt;In bowling, we roll balls down a lane, trying to knock down pins.  If we
know how many pins we knock down with each ball, we can compute the final
score.  So our program looks something like this:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;-- Pins knocked down by each ball.&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;Balls&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Int&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;

&lt;span class='comment'&gt;-- Number of points scored.&lt;/span&gt;
&lt;span class='keyword'&gt;type&lt;/span&gt; &lt;span class='conid'&gt;Score&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt;

&lt;span class='varid'&gt;scoreGame&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Balls&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Score&lt;/span&gt;
&lt;span class='varid'&gt;scoreGame&lt;/span&gt; &lt;span class='varid'&gt;balls&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varop'&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But how do we implement &lt;code&gt;scoreGame&lt;/code&gt;?&lt;/p&gt;

&lt;h3&gt;Scoring a frame&lt;/h3&gt;

&lt;p&gt;A bowling game is divided into 10 &lt;b&gt;frames&lt;/b&gt;.  Ordinary frames consist of 1 or 2 balls. The 10th frame may have an additional 1 or 2 bonus balls, which we discuss below.&lt;/p&gt;

&lt;p&gt;To score an individual frame, we need to do two things: (1) calculate the score for our frame, and (2) figure out where the next frame
starts.  Our scoring function will return both pieces of information:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='comment'&gt;-- Score one frame and return the rest.&lt;/span&gt;
&lt;span class='varid'&gt;scoreFrame&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;Balls&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Score&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Balls&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we knock down all 10 pins with the first ball in a frame
(&lt;code&gt;x1&lt;/code&gt;), we call it a &lt;b&gt;strike&lt;/b&gt;, and move on to the next
frame immediately.  But we also get a bonus&amp;#8212;we&amp;#8217;re allowed to count balls
&lt;code&gt;y1&lt;/code&gt; and &lt;code&gt;y2&lt;/code&gt; from the &lt;i&gt;next&lt;/i&gt; frame towards
&lt;i&gt;this&lt;/i&gt; frame&amp;#8217;s score:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;scoreFrame&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;    &lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;y2&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='varid'&gt;x1&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;y2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;y2&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;  &lt;span class='comment'&gt;-- Strike&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we knock down all the pins using &lt;i&gt;two&lt;/i&gt; balls (&lt;code&gt;x1&lt;/code&gt; and
&lt;code&gt;x2&lt;/code&gt;), we call it a &lt;b&gt;spare&lt;/b&gt;.  And we get to count one ball from
the next frame as our bonus:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;scoreFrame&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;x2&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;x2&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;10&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;x2&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='varid'&gt;y1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;     &lt;span class='comment'&gt;-- Spare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If we don&amp;#8217;t manage to knock all 10 pins with two balls, we call it an &lt;b&gt;open
frame&lt;/b&gt;.  And we don&amp;#8217;t get any bonus:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;scoreFrame&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;x2&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt; &lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x1&lt;/span&gt;&lt;span class='varop'&gt;+&lt;/span&gt;&lt;span class='varid'&gt;x2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;    &lt;span class='varid'&gt;ys&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;        &lt;span class='comment'&gt;-- Open frame&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What happens if we have a strike or a spare in the 10th frame?
We get to roll our bonus balls anyway.  Conventionally, these extra balls
are recorded as part of the 10th frame (making it 3 balls long), but
they&amp;#8217;re really just phantom balls hanging off the end of the game.&lt;/p&gt;

&lt;p&gt;Next, we need to turn &lt;code&gt;scoreFrame&lt;/code&gt; into a recursive function.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/04/28/bowling-in-haskell"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 28 Apr 2007 11:53:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:bdc382f2-6bcf-40f0-93ca-54c2b4de03c9</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/04/28/bowling-in-haskell</link>
      <category>Haskell</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/409</trackback:ping>
    </item>
    <item>
      <title>Robot localization using a particle system monad</title>
      <description>&lt;p&gt;&lt;b&gt;Refactoring Probability Distributions:&lt;/b&gt;
&lt;a href="http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions" title="PerhapsT"&gt;part 1&lt;/a&gt;, &lt;a href="http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions" title="Random sampling"&gt;part 2&lt;/a&gt;, &lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests" title="Bayes' rule"&gt;part 3&lt;/a&gt;, &lt;a href="http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell" title="Bayesian classification"&gt;part 4&lt;/a&gt;, &lt;b&gt;part 5&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Welcome to the 5th (and final) installment of &lt;i&gt;Refactoring Probability
Distributions!&lt;/i&gt;  Today, let&amp;#8217;s begin with an example from 
&lt;a href="http://seattle.intel-research.net/people/jhightower/pubs/fox2003bayesian/fox2003bayesian.pdf" title="Fox and colleagues, 2003"&gt;Bayesian Filters for Location Estimation&lt;/a&gt; (PDF), an excellent paper by Fox and colleagues.&lt;/p&gt;

&lt;p&gt;In their example, we have a robot in a hallway with 3 doors.  Unfortunately, we don&amp;#8217;t know &lt;i&gt;where&lt;/i&gt; in the hallway the robot is located:&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img
src="http://www.randomhacks.net/files/robot-door-1.png" title="Robot at
first door" /&gt;&lt;/p&gt;

&lt;p&gt;The vertical black lines are &amp;#8220;particles.&amp;#8221;  Each particle represents a
possible location of our robot, chosen at random along the hallway.  At
first, our particles are spread along the entire hallway (the top
row of black lines). Each particle begins life with a weight of 100%, represented by the height of the black line.&lt;/p&gt;

&lt;p&gt;Now imagine that our robot has a &amp;#8220;door sensor,&amp;#8221; which currently tells us that
we&amp;#8217;re in front of a door. This allows us to rule out any particle which is located &lt;i&gt;between&lt;/i&gt; doors. &lt;/p&gt;

&lt;p&gt;So we multiply the weight of each particle by 100% (if it&amp;#8217;s in front of a door) or 0% (if it&amp;#8217;s between doors), which gives us the lower row of particles. If our sensor was less accurate, we might use 90% and 10%, respectively.&lt;/p&gt;

&lt;p&gt;What would this example look like in Haskell?  We &lt;i&gt;could&lt;/i&gt; build a
giant list of particles (with weights), but that would require us to do a
lot of bookkeeping by hand.  Instead, we use a &lt;a href="http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes" title="Monads in 15 minutes"&gt;monad&lt;/a&gt; to hide all the
details, allowing us to work with a single particle at a time.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;localizeRobot&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;WPS&lt;/span&gt; &lt;span class='conid'&gt;Int&lt;/span&gt;
&lt;span class='varid'&gt;localizeRobot&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='comment'&gt;-- Pick a random starting location.&lt;/span&gt;
  &lt;span class='comment'&gt;-- This will be our first particle.&lt;/span&gt;
  &lt;span class='varid'&gt;pos1&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;uniform&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;0&lt;/span&gt;&lt;span class='keyglyph'&gt;..&lt;/span&gt;&lt;span class='num'&gt;299&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='comment'&gt;-- We know we're at a door.  Particles&lt;/span&gt;
  &lt;span class='comment'&gt;-- in front of a door get a weight of&lt;/span&gt;
  &lt;span class='comment'&gt;-- 100%, others get 0%.&lt;/span&gt;
  &lt;span class='keyword'&gt;if&lt;/span&gt; &lt;span class='varid'&gt;doorAtPosition&lt;/span&gt; &lt;span class='varid'&gt;pos1&lt;/span&gt;
    &lt;span class='keyword'&gt;then&lt;/span&gt; &lt;span class='varid'&gt;weight&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt;
    &lt;span class='keyword'&gt;else&lt;/span&gt; &lt;span class='varid'&gt;weight&lt;/span&gt; &lt;span class='num'&gt;0&lt;/span&gt;
  &lt;span class='comment'&gt;-- ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What happens if our robot drives forward?&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/04/19/robot-localization-particle-system-monad"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 19 Apr 2007 20:43:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:d14628b2-732e-4b87-934f-c6373df35a5c</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/04/19/robot-localization-particle-system-monad</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <category>Probability</category>
      <category>Robots</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/399</trackback:ping>
    </item>
    <item>
      <title>How to make Data.Set a monad</title>
      <description>&lt;p&gt;&lt;b&gt;&amp;#8230;and how to fake Lisp macros with Template Haskell&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;(I wrote this article in response to &lt;a href="http://www.randomhacks.net/articles/2007/03/05/three-things-i-dont-understand-about-monads#comment-329"&gt;a comment&lt;/a&gt; by
&lt;a href="http://sigfpe.blogspot.com/"&gt;sigfpe&lt;/a&gt;.  You may find it pretty dry reading, unless you want to
build &lt;a href="http://en.wikipedia.org/wiki/Domain-specific_programming_language"&gt;domain-specific languages&lt;/a&gt; in Haskell.  Proceed at your own
risk.)&lt;/p&gt;

&lt;p&gt;Haskell&amp;#8217;s built-in &lt;code&gt;Monad&lt;/code&gt; type has some serious limitations.  We can fix those limitations using a number of advanced Haskell techniques, including &lt;a href="http://www.haskell.org/th/"&gt;Template Haskell&lt;/a&gt;, Haskell&amp;#8217;s closest equivalent to Lisp macros.&lt;/p&gt;

&lt;p&gt;We can illustrate the limitations of &lt;code&gt;Monad&lt;/code&gt; with an example from math. In &lt;a href="http://en.wikipedia.org/wiki/Set_theory"&gt;set theory&lt;/a&gt;, we can define a set by specifying how to compute each
element:&lt;/p&gt;

&lt;blockquote&gt;
{ &lt;i&gt;xy&lt;/i&gt; : &lt;i&gt;x&lt;/i&gt; &amp;isin; {1,2,4}, &lt;i&gt;y&lt;/i&gt; &amp;isin; {1,2,4} }
&lt;/blockquote&gt;

&lt;p&gt;We can read this as, &amp;#8220;the set of all &lt;i&gt;xy&lt;/i&gt;, where &lt;i&gt;x&lt;/i&gt;
is one of {1,2,4}, and &lt;i&gt;y&lt;/i&gt; is one of {1,2,4}.&amp;#8221;  To calculate the
answer, we first multiply together all the possible combinations:&lt;/p&gt;

&lt;blockquote&gt;
1&amp;times;1=1, 1&amp;times;2=2, 1&amp;times;4=4, 2&amp;times;1=2, 2&amp;times;2=4, 2&amp;times;4=8, 4&amp;times;1=4, 4&amp;times;2=8, 4&amp;times;4=16
&lt;/blockquote&gt;

&lt;p&gt;We then collect up the answers, and&amp;#8212;because we&amp;#8217;re working with sets&amp;#8211;we
throw away the duplicates:&lt;/p&gt;

&lt;blockquote&gt;
{1,2,4,8,16}
&lt;/blockquote&gt;

&lt;p&gt;Can we do the same thing in Haskell?  Well, using Haskell&amp;#8217;s &lt;a href="http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes"&gt;list
monad&lt;/a&gt;, we can write:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;listExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But when we run this, Haskell gives us lots of duplicate values:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;listExample&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;16&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our problem: We&amp;#8217;re using lists (which can contain duplicate
values) to represent sets (which can&amp;#8217;t).  Can we fix this by switching to
Haskell&amp;#8217;s &lt;code&gt;Data.Set&lt;/code&gt;?&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;import&lt;/span&gt; &lt;span class='varid'&gt;qualified&lt;/span&gt; &lt;span class='conid'&gt;Data&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='keyword'&gt;as&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;

&lt;span class='comment'&gt;-- This doesn't work.&lt;/span&gt;
&lt;span class='varid'&gt;setExample&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='conid'&gt;S&lt;/span&gt;&lt;span class='varop'&gt;.&lt;/span&gt;&lt;span class='varid'&gt;fromList&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, this code fails spectacularly.  A Haskell monad is required
to work for &lt;i&gt;any&lt;/i&gt; types &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;class&lt;/span&gt; &lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='keyword'&gt;where&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='varid'&gt;fail&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;
  &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varop'&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But &lt;code&gt;Data.Set&lt;/code&gt; only works for some types.  Specifically, it
requires that values of type &lt;code&gt;a&lt;/code&gt; can be ordered:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Ord&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;Set&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varop'&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As it turns out, we can make &lt;code&gt;Data.Set&lt;/code&gt; into a monad.  But be
warned: The solution involves some pretty ugly Haskell abuse.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 15 Mar 2007 22:29:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:93c1c7e1-2355-408f-bf5e-488ce3ea0913</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/15/data-set-monad-haskell-macros</link>
      <category>Haskell</category>
      <category>Monads</category>
      <category>Macros</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/367</trackback:ping>
    </item>
    <item>
      <title>Monads in 15 minutes: Backtracking and Maybe</title>
      <description>&lt;p&gt;This morning, a programmer visited #haskell and asked how to implement
&lt;a href="http://www.randomhacks.net/articles/2005/10/11/amb-operator"&gt;backtracking&lt;/a&gt;.  Not surprisingly, most of the answers involved
monads.  After all, monads are ubiquitous in Haskell: They&amp;#8217;re used for IO,
for &lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;probability&lt;/a&gt;, for &lt;a href="http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors"&gt;error reporting&lt;/a&gt;, and even for &lt;a href="http://sigfpe.blogspot.com/2007/03/monads-vector-spaces-and-quantum.html"&gt;quantum
mechanics&lt;/a&gt;.  If you program in Haskell, you&amp;#8217;ll
probably want to understand monads.  So where&amp;#8217;s the best place to start?&lt;/p&gt;

&lt;p&gt;A friend of mine claims he didn&amp;#8217;t truly understand monads until he
understood &lt;code&gt;join&lt;/code&gt;.  But once he figured that out, everything was
suddenly obvious.  That&amp;#8217;s the way it worked for me, too.  But relatively
few monad tutorials are based on &lt;code&gt;join&lt;/code&gt;, so there&amp;#8217;s an open niche in &lt;a href="http://www.google.com/search?q=monad+tutorial"&gt;a crowded market&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This monad tutorial uses &lt;code&gt;join&lt;/code&gt;.  Even better, it attempts to
cram everything you need to know about monads into 15 minutes.  (Hey, everybody needs a gimmick, right?)&lt;/p&gt;

&lt;h3&gt;Backtracking: The lazy way to code&lt;/h3&gt;

&lt;p&gt;We begin with a &lt;a href="http://www.randomhacks.net/articles/2005/10/11/amb-operator"&gt;backtracking constraint solver&lt;/a&gt;.  The idea: Given
possible values for &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, we want to pick
those values which have a product of 8:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;solveConstraint&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;choose&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;1&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;3&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;choose&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;5&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;6&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='varid'&gt;guard&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='varop'&gt;*&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='varop'&gt;==&lt;/span&gt; &lt;span class='num'&gt;8&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;x&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='varid'&gt;y&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Every time &lt;code&gt;choose&lt;/code&gt; is called, we save the current program
state.  And every time &lt;code&gt;guard&lt;/code&gt; fails, we backtrack to a saved
state and try again.  Eventually, we&amp;#8217;ll hit the right answer:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;take&lt;/span&gt; &lt;span class='num'&gt;1&lt;/span&gt; &lt;span class='varid'&gt;solveConstraint&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='num'&gt;2&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='num'&gt;4&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;#8217;s build this program step-by-step in Haskell.  When we&amp;#8217;re done, we&amp;#8217;ll
have a monad.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 12 Mar 2007 19:39:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:3d842a23-3d7f-4ebf-877b-352ac33b863d</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes</link>
      <category>Haskell</category>
      <category>Monads</category>
      <category>Math</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/353</trackback:ping>
    </item>
    <item>
      <title>8 ways to report errors in Haskell</title>
      <description>&lt;p&gt;Haskell is a marvellous language, but there are some things I don&amp;#8217;t like about it.  My least favorite: Haskell has no fewer than 8
different APIs for reporting errors.&lt;/p&gt;

&lt;p&gt;To make a bad situation worse, the choice of API varies between 
popular libraries. To give a particularly unfortunate example,
&lt;a href="http://haskell.org/ghc/docs/latest/html/libraries/network/Network-URI.html"&gt;Network.URI.parseURI&lt;/a&gt; and &lt;a href="http://www.haskell.org/http/api/Network-HTTP.html"&gt;Network.HTTP.simpleHTTP&lt;/a&gt; report
errors in entirely different ways, turning a &amp;#8220;download this URL&amp;#8221; program into a &lt;a href="http://darcs.haskell.org/http/test/get.hs"&gt;page of code&lt;/a&gt;,
nearly half of which is devoted to dealing with various kinds of errors. (The rest is boilerplate that could be refactored into a nice wrapper.)&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s begin with a toy function, the simplest possible program that could
actually fail:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;myDiv&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;x&lt;/span&gt; &lt;span class='varop'&gt;/&lt;/span&gt; &lt;span class='varid'&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As every algebra student knows, we can&amp;#8217;t divide by zero.  Using this
function as our example, let&amp;#8217;s take a look at all the different ways we
can implement error-reporting in Haskell.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 10 Mar 2007 19:05:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:226356a7-21bf-493b-aa23-59dccc766054</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors</link>
      <category>Haskell</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/347</trackback:ping>
    </item>
    <item>
      <title>Three things I don't understand about monads</title>
      <description>&lt;p&gt;Monads are a remarkably powerful tool for building specialized programming languages.  Some examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.cs.uu.nl/~daan/parsec.html"&gt;Parsers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;Bayesian inference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://web.cecs.pdx.edu/~mpj/pubs/modinterp.html"&gt;Modular interpreters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there&amp;#8217;s a bunch of things I don&amp;#8217;t understand about monads. In each case, my confusion involves some aspect of the underlying math that &amp;#8220;bubbles up&amp;#8221; to affect the design of specialized languages.&lt;/p&gt;

&lt;p&gt;(Warning: Obscure monad geeking ahead.)&lt;/p&gt;

&lt;h3&gt;Commutative monads&lt;/h3&gt;

&lt;p&gt;A &amp;#8220;commutative monad&amp;#8221; is any monad where we can replace the expression:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;do&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;ma&lt;/span&gt;
   &lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;mb&lt;/span&gt;
   &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;#8230;with:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;do&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;mb&lt;/span&gt;
   &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;ma&lt;/span&gt;
   &lt;span class='varid'&gt;f&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt; &lt;span class='varid'&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&amp;#8230;without changing the meaning. Examples of commutative monads include &lt;code&gt;Reader&lt;/code&gt; and &lt;code&gt;Rand&lt;/code&gt;.  This is an important property, because it might allow us to parallelize the commonly-used &lt;code&gt;sequence&lt;/code&gt; function across huge numbers of processors:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;sequence&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Monad&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='varid'&gt;a&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Simon Peyton Jones lists this problem as &lt;a href="http://research.microsoft.com/~simonpj/papers/haskell-retrospective/index.htm"&gt;Open Challenge #2&lt;/a&gt;, saying:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Commutative monads are very common.  (Environment, 
unique supply, random number generation.)  For these, monads over-sequentialise.&lt;/p&gt; &lt;p&gt;Wanted: theory and notation for some cool compromise.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h3&gt;Commutative monad morphisms&lt;/h3&gt;

&lt;p&gt;&lt;strike&gt;Monad morphisms are the category theory equivalent of Haskell&amp;#8217;s &lt;a href="http://www.haskell.org/all_about_monads/html/transformers.html"&gt;monad transformers&lt;/a&gt;.&lt;/strike&gt; &lt;i&gt;Haskell&amp;#8217;s monad transformers &lt;a href="http://conway.rutgers.edu/~ccshan/wiki/blog/posts/Monad_transformers.html"&gt;can be expressed as&lt;/a&gt; monad layerings, which &lt;a href="http://sigfpe.blogspot.com/2007/02/monads-for-vector-spaces-probability.html#3140655259397671649"&gt;correspond&lt;/a&gt; to the monad morphisms of category theory.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Many complicated monads &lt;a href="http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions"&gt;break down into a handful of monad transformers&lt;/a&gt;, often in surprising ways.&lt;/p&gt;

&lt;p&gt;But composing monad transformers is a mess, because they interact in poorly-understood ways. In general, the following two types have very different semantics:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='conid'&gt;FooT&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;BarT&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='conid'&gt;BarT&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;FooT&lt;/span&gt; &lt;span class='varid'&gt;m&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code&gt;FooT&lt;/code&gt; and &lt;code&gt;BarT&lt;/code&gt; commute with each other, however, the two types would be equivalent. This is helpful when building large stacks of monad transformers. &lt;/p&gt;

&lt;p&gt;Chung-chieh Shan encountered a related problem when applying monad morphisms to build a &lt;a href="http://arxiv.org/abs/cs.CL/0205026"&gt;theory of natural language semantics&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;It remains to be seen whether monads would provide the appropriate 
conceptual encapsulation for a semantic theory with broader coverage. In 
particular, for both natural and programming language semantics, combining monads&amp;#8212;or perhaps monad-like objects&amp;#8212;remains an open issue that 
promises additional insight.&lt;/blockquote&gt;

&lt;h3&gt;Monad morphisms and abstract algebra&lt;/h3&gt;

&lt;p&gt;Dan Piponi has been drawing some fascinating connections between monad morphisms and abstract algebra. See, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://sigfpe.blogspot.com/2006/11/why-isnt-listt-monad.html"&gt;Why isn&amp;#8217;t ListT ([]) a monad?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://sigfpe.blogspot.com/2007/02/monads-for-vector-spaces-probability.html"&gt;Monads for vector spaces, probability and quantum mechanics pt. I&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach seems to throw a lot of light on monad morphisms&amp;#8212;but at least in my case, the light only highlights my confusion.&lt;/p&gt;

&lt;p&gt;Of the three problems listed here, this is the one most likely to be discussed in a textbook somewhere. And a solution to this problem would likely help significantly with the other two.&lt;/p&gt;

&lt;p&gt;So, my question: Does anybody have any books, papers or ideas that might help untangle this mess?&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Update: Be sure to see the comment thread on the &lt;a href="http://sigfpe.blogspot.com/2007/02/monads-for-vector-spaces-probability.html"&gt;second Dan Piponi post&lt;/a&gt; above and Chung-chieh Shan&amp;#8217;s &lt;a href="http://conway.rutgers.edu/~ccshan/wiki/blog/posts/Monad_transformers.html"&gt;excellent bibliography on monad transformers&lt;/a&gt;.&lt;/i&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 05 Mar 2007 09:32:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:5db7d37a-2c34-4366-b6f0-64877955b837</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/05/three-things-i-dont-understand-about-monads</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/326</trackback:ping>
    </item>
    <item>
      <title>Smart classification using Bayesian monads in Haskell</title>
      <description>&lt;p&gt;&lt;small&gt;(Refactoring Probability Distributions: &lt;a href="http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions"&gt;part 1&lt;/a&gt;, &lt;a href="http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions"&gt;part 2&lt;/a&gt;,
&lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;part 3&lt;/a&gt;, &lt;b&gt;part 4&lt;/b&gt;)&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The world is full of messy classification problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;#8220;Is this order fraudulent?&amp;#8221;&lt;/li&gt;
&lt;li&gt;&amp;#8220;It this e-mail a spam?&amp;#8221;&lt;/li&gt;
&lt;li&gt;&amp;#8220;What blog posts would Rachel find interesting?&amp;#8221;&lt;/li&gt;
&lt;li&gt;&amp;#8220;Which intranet documents is Sam looking for?&amp;#8221;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each case, we want to classify something: Orders are either valid or
fraudulent, messages are either spam or non-spam, blog posts are either
interesting or boring.  Unfortunately, most software is &lt;i&gt;terrible&lt;/i&gt; at
making these distinctions.  For example, why can&amp;#8217;t my RSS reader go out and
track down the 10 most interesting blog posts every day?&lt;/p&gt;

&lt;p&gt;Some software, however, &lt;i&gt;can&lt;/i&gt; make these distinctions.
Google figures out when I want to watch a movie, and shows me &lt;a href="http://www.google.com/search?q=cinema+boston"&gt;specialized
search results&lt;/a&gt;.  And most e-mail clients can identify spam with over
99% accuracy.  But the vast majority of software is dumb, incapable of
dealing with the messy dilemmas posed by the real world.&lt;/p&gt;

&lt;p&gt;So where can we learn to improve our software?&lt;/p&gt;

&lt;p&gt;Outside of Google&amp;#8217;s shroud
of secrecy, the most successful classifiers are spam filters.  And most modern
spam filters are inspired by Paul Graham&amp;#8217;s essay &lt;a href="http://www.paulgraham.com/spam.html"&gt;A Plan for Spam&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let&amp;#8217;s go back to the source, and see what we can learn.  As it turns out, we can formulate a lot of the ideas in &lt;a href="http://www.paulgraham.com/spam.html"&gt;A Plan
for Spam&lt;/a&gt; in a straightforward fashion using a &lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;Bayesian
monad&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Functions from distributions to distributions&lt;/h3&gt;

&lt;p&gt;Let&amp;#8217;s begin with spam filtering.  By convention, we divide messages into
&amp;#8220;spam&amp;#8221; and &amp;#8220;ham&amp;#8221;, where &amp;#8220;ham&amp;#8221; is the stuff we want to read.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='keyword'&gt;data&lt;/span&gt; &lt;span class='conid'&gt;MsgType&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='conid'&gt;Spam&lt;/span&gt; &lt;span class='keyglyph'&gt;|&lt;/span&gt; &lt;span class='conid'&gt;Ham&lt;/span&gt;
  &lt;span class='keyword'&gt;deriving&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='conid'&gt;Show&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Eq&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Enum&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Bounded&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;#8217;s assume that we&amp;#8217;ve just received a new e-mail.  Without even looking
at it, we know there&amp;#8217;s a certain chance that it&amp;#8217;s a spam.  This gives us
something called a &amp;#8220;prior distribution&amp;#8221; over &lt;code&gt;MsgType&lt;/code&gt;.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;bayes&lt;/span&gt; &lt;span class='varid'&gt;msgTypePrior&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Spam&lt;/span&gt; &lt;span class='num'&gt;64.2&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Ham&lt;/span&gt; &lt;span class='num'&gt;35.8&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But what if we know that the first word of the message is &amp;#8220;free&amp;#8221;?  We can
use that information to calculate a new distribution.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;bayes&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;hasWord&lt;/span&gt; &lt;span class='str'&gt;"free"&lt;/span&gt; &lt;span class='varid'&gt;msgTypePrior&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Spam&lt;/span&gt; &lt;span class='num'&gt;90.5&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Ham&lt;/span&gt; &lt;span class='num'&gt;9.5&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function &lt;code&gt;hasWord&lt;/code&gt; takes a string and a probability
distribution, and uses them to calculate a new probability distribution:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;hasWord&lt;/span&gt; &lt;span class='keyglyph'&gt;::&lt;/span&gt; &lt;span class='conid'&gt;String&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='conid'&gt;FDist'&lt;/span&gt; &lt;span class='conid'&gt;MsgType&lt;/span&gt; &lt;span class='keyglyph'&gt;-&amp;gt;&lt;/span&gt;
           &lt;span class='conid'&gt;FDist'&lt;/span&gt; &lt;span class='conid'&gt;MsgType&lt;/span&gt;
&lt;span class='varid'&gt;hasWord&lt;/span&gt; &lt;span class='varid'&gt;word&lt;/span&gt; &lt;span class='varid'&gt;prior&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;msgType&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='varid'&gt;prior&lt;/span&gt;
  &lt;span class='varid'&gt;wordPresent&lt;/span&gt; &lt;span class='keyglyph'&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class='varid'&gt;wordPresentDist&lt;/span&gt; &lt;span class='varid'&gt;msgType&lt;/span&gt; &lt;span class='varid'&gt;word&lt;/span&gt;
  &lt;span class='varid'&gt;condition&lt;/span&gt; &lt;span class='varid'&gt;wordPresent&lt;/span&gt;
  &lt;span class='varid'&gt;return&lt;/span&gt; &lt;span class='varid'&gt;msgType&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code is based on the Bayesian monad from &lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;part 3&lt;/a&gt;.  As before,
the &amp;ldquo;&lt;code&gt;&amp;lt;-&lt;/code&gt;&amp;#8221; operator selects a single item from a probability
distribution, and &amp;#8220;condition&amp;#8221; asserts that an expression is true.  The
actual Bayesian inference happens behind the scenes (handy, that).&lt;/p&gt;

&lt;p&gt;If we have multiple pieces of evidence, we can apply them one at a time.
Each piece of evidence will update the probability distribution produced by
the previous step:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varid'&gt;hasWords&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;     &lt;span class='varid'&gt;prior&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='varid'&gt;prior&lt;/span&gt;
&lt;span class='varid'&gt;hasWords&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;w&lt;/span&gt;&lt;span class='conop'&gt;:&lt;/span&gt;&lt;span class='varid'&gt;ws&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt; &lt;span class='varid'&gt;prior&lt;/span&gt; &lt;span class='keyglyph'&gt;=&lt;/span&gt; &lt;span class='keyword'&gt;do&lt;/span&gt;
  &lt;span class='varid'&gt;hasWord&lt;/span&gt; &lt;span class='varid'&gt;w&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;hasWords&lt;/span&gt; &lt;span class='varid'&gt;ws&lt;/span&gt; &lt;span class='varid'&gt;prior&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The final distribution will combine everything we know:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='varid'&gt;bayes&lt;/span&gt; &lt;span class='layout'&gt;(&lt;/span&gt;&lt;span class='varid'&gt;hasWords&lt;/span&gt; &lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='str'&gt;"free"&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt;&lt;span class='str'&gt;"bayes"&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt; &lt;span class='varid'&gt;msgTypePrior&lt;/span&gt;&lt;span class='layout'&gt;)&lt;/span&gt;
&lt;span class='keyglyph'&gt;[&lt;/span&gt;&lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Spam&lt;/span&gt; &lt;span class='num'&gt;34.7&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='layout'&gt;,&lt;/span&gt; &lt;span class='conid'&gt;Perhaps&lt;/span&gt; &lt;span class='conid'&gt;Ham&lt;/span&gt; &lt;span class='num'&gt;65.3&lt;/span&gt;&lt;span class='varop'&gt;%&lt;/span&gt;&lt;span class='keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This technique is known as the &lt;a href="http://en.wikipedia.org/wiki/Naive_Bayes_classifier"&gt;naive Bayes classifier&lt;/a&gt;.  Looked at from the right angle, it&amp;#8217;s surprisingly simple.&lt;/p&gt;

&lt;p&gt;(Of course, the naive Bayes classifier assumes that all of our evidence is independent.  In theory, this is a pretty big assumption. In practice, it &lt;a href="http://www.cs.unb.ca/profs/hzhang/publications/FLAIRS04ZhangH.pdf"&gt;works better than you might think&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;But this still leaves us with a lot of questions: How do we keep track of
our different classifiers?  How do we decide which ones to apply?  And do
we need to fudge the numbers to get reasonable results?&lt;/p&gt;

&lt;p&gt;In the following sections, I&amp;#8217;ll walk through various aspects of Paul
Graham&amp;#8217;s &lt;a href="http://www.paulgraham.com/spam.html"&gt;A Plan for Spam&lt;/a&gt;, and show how to generalize it.  If you
want to follow along, you can download the code using Darcs:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_sh "&gt;darcs get http://www.randomhacks.net/darcs/probability&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 03 Mar 2007 09:02:00 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:46da7ba0-d82a-40a5-bdac-d730e4f7073b</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <category>Probability</category>
      <category>Spam</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/322</trackback:ping>
    </item>
  </channel>
</rss>
