<?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 Math</title>
    <link>http://www.randomhacks.net/articles/tag/Math?tag=Math</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>Derivatives of algebraic data structures: An excellent tutorial</title>
      <description>&lt;p&gt;Last month, the folks at Lab49 explained &lt;a href="http://blog.lab49.com/archives/3011"&gt;how to compute the derivative of a data structure&lt;/a&gt;. This is a great example of how to write about mathematical subjects for a casual audience: They draw analogies to well-known programming languages, they follow a single, well-chosen thread of explanation, and there&amp;#8217;s a clever payoff at the end.&lt;/p&gt;

&lt;p&gt;The Lab49 blog post is, of course, based on two &lt;a href="http://strictlypositive.org/diff.pdf"&gt;classic&lt;/a&gt; &lt;a href="http://strictlypositive.org/Dissect.pdf"&gt;papers&lt;/a&gt; by Conor McBride, and Huet&amp;#8217;s original paper &lt;a href="http://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf"&gt;The Zipper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re interested in real-world applications of this technique, there&amp;#8217;s a great explanation in the final chapter of &lt;a href="http://learnyouahaskell.com/zippers"&gt;Learn You a Haskell for Great Good&lt;/a&gt;. If you&amp;#8217;re interested in some deeper mathematical connections, see the &lt;a href="http://lambda-the-ultimate.org/node/1957"&gt;discussion at Lambda the Ultimate&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Fri, 20 May 2011 20:01:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:1f6b612b-f3cd-4f3a-8442-d23ce7769c8c</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2011/05/20/derivatives-of-algebraic-data-structures-an-excellent-tutorial</link>
      <category>Haskell</category>
      <category>Math</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/836</trackback:ping>
    </item>
    <item>
      <title>What do these fixed points have in common?</title>
      <description>&lt;p&gt;A question asked while standing in the shower: What do all of the following have in common?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Banach_fixed_point_theorem"&gt;Banach&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Brouwer_fixed_point_theorem"&gt;Brouwer fixed points&lt;/a&gt;. If you&amp;#8217;re in Manhattan, and you crumple up a map of Manhattan and place it on the ground, at least one point on your map will be exactly over the corresponding point on the ground. (This is true even if your map is &lt;em&gt;larger&lt;/em&gt; than life.)&lt;/li&gt;
&lt;li&gt;The fixed points computed by the &lt;a href="http://en.wikipedia.org/wiki/Fixed_point_combinator"&gt;Y combinator&lt;/a&gt;, which is used to construct anonymous recursive functions in the lambda calculus.&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/Nash_equilibrium"&gt;Nash equilibrium&lt;/a&gt;, which is the stable equilibrium of a multi-player game (and one of the key ideas of economics). See also this lovely—if metaphorical—&lt;a href="http://www.scottaaronson.com/blog/?p=418"&gt;rant by Scott Aaronson&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://en.wikipedia.org/wiki/Eigenvector"&gt;eigenvectors of a matrix&lt;/a&gt;, which will still point in the same direction after multiplication by the matrix.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At what level of abstraction are all these important ideas really just the same idea? If we strip everything down to &lt;a href="http://en.wikipedia.org/wiki/Abstract_nonsense"&gt;generalized abstract nonsense&lt;/a&gt;, is there a nice simple formulation that covers all of the above?&lt;/p&gt;

&lt;p&gt;(I can&amp;#8217;t play with this shiny toy today; I have to work.)&lt;/p&gt;</description>
      <pubDate>Thu, 12 May 2011 12:09:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:59fdd543-cb2f-4186-8d02-7ddf121ccc7c</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2011/05/12/what-do-fixed-points-have-in-common</link>
      <category>Math</category>
      <category>Haskell</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/832</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 +0000</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>
      <category>ProbabilityMonads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/509</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='hs-definition'&gt;localizeRobot&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;WPS&lt;/span&gt; &lt;span class='hs-conid'&gt;Int&lt;/span&gt;
&lt;span class='hs-definition'&gt;localizeRobot&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-comment'&gt;-- Pick a random starting location.&lt;/span&gt;
  &lt;span class='hs-comment'&gt;-- This will be our first particle.&lt;/span&gt;
  &lt;span class='hs-varid'&gt;pos1&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;uniform&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-num'&gt;0&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;..&lt;/span&gt;&lt;span class='hs-num'&gt;299&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='hs-comment'&gt;-- We know we're at a door.  Particles&lt;/span&gt;
  &lt;span class='hs-comment'&gt;-- in front of a door get a weight of&lt;/span&gt;
  &lt;span class='hs-comment'&gt;-- 100%, others get 0%.&lt;/span&gt;
  &lt;span class='hs-keyword'&gt;if&lt;/span&gt; &lt;span class='hs-varid'&gt;doorAtPosition&lt;/span&gt; &lt;span class='hs-varid'&gt;pos1&lt;/span&gt;
    &lt;span class='hs-keyword'&gt;then&lt;/span&gt; &lt;span class='hs-varid'&gt;weight&lt;/span&gt; &lt;span class='hs-num'&gt;1&lt;/span&gt;
    &lt;span class='hs-keyword'&gt;else&lt;/span&gt; &lt;span class='hs-varid'&gt;weight&lt;/span&gt; &lt;span class='hs-num'&gt;0&lt;/span&gt;
  &lt;span class='hs-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 +0000</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>
      <category>ProbabilityMonads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/399</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='hs-definition'&gt;solveConstraint&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-varid'&gt;x&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;choose&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-num'&gt;1&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-num'&gt;2&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-num'&gt;3&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='hs-varid'&gt;y&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;choose&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-num'&gt;4&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-num'&gt;5&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-num'&gt;6&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
  &lt;span class='hs-varid'&gt;guard&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;x&lt;/span&gt;&lt;span class='hs-varop'&gt;*&lt;/span&gt;&lt;span class='hs-varid'&gt;y&lt;/span&gt; &lt;span class='hs-varop'&gt;==&lt;/span&gt; &lt;span class='hs-num'&gt;8&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
  &lt;span class='hs-varid'&gt;return&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;x&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-varid'&gt;y&lt;/span&gt;&lt;span class='hs-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='hs-varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;take&lt;/span&gt; &lt;span class='hs-num'&gt;1&lt;/span&gt; &lt;span class='hs-varid'&gt;solveConstraint&lt;/span&gt;
&lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-num'&gt;2&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-num'&gt;4&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;&lt;span class='hs-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 +0000</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>Jim Hefferon's Linear Algebra: A free textbook with fascinating applications</title>
      <description>&lt;p style="text-align: center"&gt;&lt;big&gt;&lt;a href="http://joshua.smcvt.edu/linearalgebra/book.pdf"&gt;Download the free book&lt;/a&gt;&lt;/big&gt; or &lt;a href="http://joshua.smcvt.edu/linearalgebra/book.pdf"&gt;visit the official site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My college linear algebra course was held early in the morning, and
it was devoted almost entirely to blackboard proofs.  The professor would
stand in front of the room, half asleep, and write:&lt;/p&gt;

&lt;p&gt;&amp;#8220;Theorem.  Lemma.  Lemma.  Proof.  Theorem&amp;#8230;&amp;#8221;&lt;/p&gt;

&lt;p&gt;Despite this experience, I somehow managed to learn about eigenvectors
and kernels.  Or at least, I learned how to write proofs about them.  But I
had no intuition for linear algebra: I couldn&amp;#8217;t visualize it, and I couldn&amp;#8217;t
explain why anybody, anywhere, ever &lt;i&gt;cared&lt;/i&gt; about eigenvectors.&lt;/p&gt;

&lt;p&gt;Years later, in a computer vision class, I finally learned to care about
linear algebra.  It could solve all sorts of cool problems!
(&lt;a href="http://en.wikipedia.org/wiki/Eigenface"&gt;Eigenfaces&lt;/a&gt;, in particular, blew me away.)  And since then, I&amp;#8217;ve
encountered linear algebra everywhere.  But my intuition is still
piecemeal, built from half-a-dozen applications over the years.&lt;/p&gt;

&lt;p&gt;My motto for math is, &amp;#8220;If it keeps showing up, build a rock-solid intuition
for how it works.&amp;#8221;  And towards that end, I&amp;#8217;ve been looking for a good
linear algebra textbook.&lt;/p&gt;

&lt;p&gt;My ideal linear algebra textbook would:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Include plenty of motivating examples.&lt;/li&gt;
&lt;li&gt;Show how to solve real-world problems.&lt;/li&gt;
&lt;li&gt;Devote plenty of time to proofs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The proofs, after all, are necessary in the real world.  If you ever
attempt to do something &lt;a href="http://www.randomhacks.net/articles/2007/03/03/smart-classification-with-haskell"&gt;slightly odd&lt;/a&gt;, you&amp;#8217;ll want to
prove that it actually works.&lt;/p&gt;

&lt;h3&gt;Jim Hefferon&amp;#8217;s &lt;i&gt;Linear Algebra&lt;/i&gt;&lt;/h3&gt;

&lt;p&gt;Professor Jim Hefferon&amp;#8217;s &lt;i&gt;Linear Algebra&lt;/i&gt; is available as a &lt;a href="http://joshua.smcvt.edu/linearalgebra/"&gt;free PDF
download&lt;/a&gt;. But don&amp;#8217;t be fooled by the price: Hefferon&amp;#8217;s book is
better than most of the expensive tomes sold in college bookstores.&lt;/p&gt;

&lt;p&gt;Everything in Hefferon&amp;#8217;s book is superbly motivated.  The first chapter
begins with two real-world examples: Unknown weights placed on balances,
and the ratios of complex molecules in chemical reactions.  These examples
are used to introduce Gauss&amp;#8217;s method for solving systems of linear
equations.  Further into the book, the examples begin to tie back to
earlier chapters.  Determinants, for example, are motivated by the
usefulness of recognizing isomorphisms and invertible matrices.&lt;/p&gt;

&lt;p&gt;But Hefferon&amp;#8217;s emphasis on real-world examples is admirably balanced by an
abundance of proofs.  The first proof appears on page 4, and nearly
everything is proven either in the main text or in the exercises.  This
will be helpful for readers who (like me) are trying to bring more rigor to
their mathematical thinking.&lt;/p&gt;

&lt;h3&gt;The &amp;#8220;Topics&amp;#8221;: Fascinating real-world problems&lt;/h3&gt;

&lt;p&gt;The most delightful part of the book, however, are the &amp;#8220;Topics&amp;#8221; at the end
of each chapter.  These cover a &lt;a href="http://joshua.smcvt.edu/linearalgebra/toc.html"&gt;wide range&lt;/a&gt; of fields, including biology,
economics, probability and abstract algebra.  The topic &amp;#8220;Stable
Populations&amp;#8221; begins:&lt;/p&gt;

&lt;blockquote&gt;Imagine a reserve park with animals from a species that we are
trying to protect.  The park doesn’t have a fence and so animals cross the
boundary, both from the inside out and in the other direction. Every year,
10% of the animals from inside of the park leave, and 1% of the animals
from the outside find their way in. We can ask if we can find a stable
level of population for this park: is there a population that, once
established, will stay constant over time, with the number of animals
leaving equal to the number of animals entering?&lt;/blockquote&gt;

&lt;p&gt;Hefferon relates the solution to Markov chains and eigenvalues, cementing
several important intuitions firmly in place.&lt;/p&gt;

&lt;p&gt;Other topics include basic electronics, space shuttle O-rings, and the
number of games required to win the World Series.  There are plenty of
CS-related discussions, too: a survey of things that can go wrong in naive
numeric code, the time required to calculate determinants, and
how the memory hierarchy affects array layout.&lt;/p&gt;

&lt;p&gt;Hefferon&amp;#8217;s love for linear algebra is infectious, and his &amp;#8220;Topics&amp;#8221; will
appeal to anybody who does recreational math.&lt;/p&gt;

&lt;h3&gt;&amp;#8220;Free&amp;#8221; as in &amp;#8220;freedom&amp;#8221;&lt;/h3&gt;

&lt;p&gt;&lt;i&gt;Linear Algebra&lt;/i&gt; is published under the &lt;a href="http://www.gnu.org/copyleft/fdl.html"&gt;GNU Free Documentation
License&lt;/a&gt; and the &lt;a href="http://creativecommons.org/licenses/by-sa/2.5/"&gt;Creative Commons Share Alike&lt;/a&gt; license.&lt;/p&gt;

&lt;p&gt;What
this means: You may make copies of the book, or even print them out at a
copyshop and charge students a fee.  You may also create a custom version of
the textbook, and share it with anybody who&amp;#8217;s interested.  The only
restriction: You must &amp;#8220;share alike,&amp;#8221; honoring the original author&amp;#8217;s terms
as you pass along the textbook.&lt;/p&gt;

&lt;h3&gt;Miscellaneous notes&lt;/h3&gt;

&lt;p&gt;Hefferon has put out a call for extra material.  In particular, he&amp;#8217;d love
to have a section on quantum mechanics:&lt;/p&gt;

&lt;blockquote&gt;Several people have asked me about a Topic on eigenvectors and
eigenvalues in Quantum Mechanics. Sadly, I don&amp;#8217;t know any QM. If you can
help, that&amp;#8217;d be great.&lt;/blockquote&gt;

&lt;p&gt;On the downside, the internal PDF links in &lt;i&gt;Linear Algebra&lt;/i&gt; are broken
in MacOS X Preview.  This is odd, because the LaTeX &lt;code&gt;hyperref&lt;/code&gt;
package usually works fine with Preview.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://programming.reddit.com/info/1129o/comments"&gt;reddit&lt;/a&gt; discussion of
&lt;i&gt;Linear Algebra&lt;/i&gt; has pointers to several other linear algebra textbooks, with varying emphasis. And many other &lt;a href="http://www.math.gatech.edu/~cain/textbooks/onlinebooks.html"&gt;free math
textbooks&lt;/a&gt; are available online.  &lt;/p&gt;

&lt;p&gt;If you have any favorite math books (paper or PDF, for any area of
mathematics), please feel free to recommend them in the comment thread!&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;big&gt;&lt;a href="http://joshua.smcvt.edu/linearalgebra/book.pdf"&gt;Download the free book&lt;/a&gt;&lt;/big&gt; or &lt;a href="http://joshua.smcvt.edu/linearalgebra/book.pdf"&gt;visit the official site&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 07 Mar 2007 08:01:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:413e2cc5-fe86-4c3d-a313-1d96098b939d</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/03/07/hefferon-linear-algebra-review</link>
      <category>Math</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/333</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='hs-keyword'&gt;do&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;ma&lt;/span&gt;
   &lt;span class='hs-varid'&gt;b&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;mb&lt;/span&gt;
   &lt;span class='hs-varid'&gt;f&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt; &lt;span class='hs-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='hs-keyword'&gt;do&lt;/span&gt; &lt;span class='hs-varid'&gt;b&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;mb&lt;/span&gt;
   &lt;span class='hs-varid'&gt;a&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;ma&lt;/span&gt;
   &lt;span class='hs-varid'&gt;f&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt; &lt;span class='hs-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='hs-definition'&gt;sequence&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Monad&lt;/span&gt; &lt;span class='hs-varid'&gt;m&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-varid'&gt;m&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;m&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-varid'&gt;a&lt;/span&gt;&lt;span class='hs-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='hs-conid'&gt;FooT&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;BarT&lt;/span&gt; &lt;span class='hs-varid'&gt;m&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;span class='hs-conid'&gt;BarT&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;FooT&lt;/span&gt; &lt;span class='hs-varid'&gt;m&lt;/span&gt;&lt;span class='hs-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 +0000</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='hs-keyword'&gt;data&lt;/span&gt; &lt;span class='hs-conid'&gt;MsgType&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-conid'&gt;Spam&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;|&lt;/span&gt; &lt;span class='hs-conid'&gt;Ham&lt;/span&gt;
  &lt;span class='hs-keyword'&gt;deriving&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Show&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Eq&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Enum&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Bounded&lt;/span&gt;&lt;span class='hs-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='hs-varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;bayes&lt;/span&gt; &lt;span class='hs-varid'&gt;msgTypePrior&lt;/span&gt;
&lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Spam&lt;/span&gt; &lt;span class='hs-num'&gt;64.2&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Ham&lt;/span&gt; &lt;span class='hs-num'&gt;35.8&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-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='hs-varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;bayes&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;hasWord&lt;/span&gt; &lt;span class='hs-str'&gt;"free"&lt;/span&gt; &lt;span class='hs-varid'&gt;msgTypePrior&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Spam&lt;/span&gt; &lt;span class='hs-num'&gt;90.5&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Ham&lt;/span&gt; &lt;span class='hs-num'&gt;9.5&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-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='hs-definition'&gt;hasWord&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;String&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='hs-conid'&gt;FDist'&lt;/span&gt; &lt;span class='hs-conid'&gt;MsgType&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt;
           &lt;span class='hs-conid'&gt;FDist'&lt;/span&gt; &lt;span class='hs-conid'&gt;MsgType&lt;/span&gt;
&lt;span class='hs-definition'&gt;hasWord&lt;/span&gt; &lt;span class='hs-varid'&gt;word&lt;/span&gt; &lt;span class='hs-varid'&gt;prior&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-varid'&gt;msgType&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;prior&lt;/span&gt;
  &lt;span class='hs-varid'&gt;wordPresent&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class='hs-varid'&gt;wordPresentDist&lt;/span&gt; &lt;span class='hs-varid'&gt;msgType&lt;/span&gt; &lt;span class='hs-varid'&gt;word&lt;/span&gt;
  &lt;span class='hs-varid'&gt;condition&lt;/span&gt; &lt;span class='hs-varid'&gt;wordPresent&lt;/span&gt;
  &lt;span class='hs-varid'&gt;return&lt;/span&gt; &lt;span class='hs-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='hs-definition'&gt;hasWords&lt;/span&gt; &lt;span class='hs-conid'&gt;[]&lt;/span&gt;     &lt;span class='hs-varid'&gt;prior&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-varid'&gt;prior&lt;/span&gt;
&lt;span class='hs-definition'&gt;hasWords&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;w&lt;/span&gt;&lt;span class='hs-conop'&gt;:&lt;/span&gt;&lt;span class='hs-varid'&gt;ws&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-varid'&gt;prior&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-varid'&gt;hasWord&lt;/span&gt; &lt;span class='hs-varid'&gt;w&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;hasWords&lt;/span&gt; &lt;span class='hs-varid'&gt;ws&lt;/span&gt; &lt;span class='hs-varid'&gt;prior&lt;/span&gt;&lt;span class='hs-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='hs-varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;bayes&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;hasWords&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-str'&gt;"free"&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-str'&gt;"bayes"&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt; &lt;span class='hs-varid'&gt;msgTypePrior&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Spam&lt;/span&gt; &lt;span class='hs-num'&gt;34.7&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-conid'&gt;Ham&lt;/span&gt; &lt;span class='hs-num'&gt;65.3&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-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 +0000</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>
      <category>ProbabilityMonads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/322</trackback:ping>
    </item>
    <item>
      <title>Bayes' rule in Haskell, or why drug tests don't work</title>
      <description>&lt;p&gt;Part 3 of Refactoring Probability Distributions.&lt;br /&gt;
&lt;small&gt;(Part 1: &lt;a href="http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions"&gt;PerhapsT&lt;/a&gt;,
Part 2: &lt;a href="http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions"&gt;Sampling functions&lt;/a&gt;)&lt;/small&gt;&lt;/p&gt;

&lt;blockquote&gt;
    &lt;p&gt;&lt;i&gt;A very senior Microsoft developer who moved to Google told
    me that Google works and thinks at a higher level of abstraction than
    Microsoft. &amp;#8220;Google uses Bayesian filtering the way Microsoft uses the if
    statement,&amp;#8221; he said.&lt;/i&gt; -&lt;a href="http://www.joelonsoftware.com/oldnews/pages/October2005.html"&gt;Joel Spolsky&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I really love this quote, because it&amp;#8217;s &lt;a href="http://weblog.raganwald.com/archives/2005_10_01_archive.html"&gt;insanely provocative&lt;/a&gt;
to any language designer.  What &lt;i&gt;would&lt;/i&gt; a programming language look
like if Bayes&amp;#8217; rule were as simple as an &lt;code&gt;if&lt;/code&gt; statement?&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start with a toy problem, and refactor it until Bayes&amp;#8217; rule is baked
right into our programming language.&lt;/p&gt;

&lt;p&gt;Imagine, for a moment, that we&amp;#8217;re in charge of administering drug tests for
a small business.  We&amp;#8217;ll represent each employee&amp;#8217;s test results (and drug use) as follows:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='hs-keyword'&gt;data&lt;/span&gt; &lt;span class='hs-conid'&gt;Test&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-conid'&gt;Pos&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;|&lt;/span&gt; &lt;span class='hs-conid'&gt;Neg&lt;/span&gt;
  &lt;span class='hs-keyword'&gt;deriving&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Show&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Eq&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;

&lt;span class='hs-keyword'&gt;data&lt;/span&gt; &lt;span class='hs-conid'&gt;HeroinStatus&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-conid'&gt;User&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;|&lt;/span&gt; &lt;span class='hs-conid'&gt;Clean&lt;/span&gt;
  &lt;span class='hs-keyword'&gt;deriving&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Show&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Eq&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Assuming that 0.1% of our employees have used heroin recently, and that our test is 99%
accurate, we can model the testing process as follows:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='hs-definition'&gt;drugTest1&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;Dist&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;HeroinStatus&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Test&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;span class='hs-definition'&gt;drugTest1&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-varid'&gt;heroinStatus&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;percentUser&lt;/span&gt; &lt;span class='hs-num'&gt;0.1&lt;/span&gt;
  &lt;span class='hs-varid'&gt;testResult&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class='hs-keyword'&gt;if&lt;/span&gt; &lt;span class='hs-varid'&gt;heroinStatus&lt;/span&gt; &lt;span class='hs-varop'&gt;==&lt;/span&gt; &lt;span class='hs-conid'&gt;User&lt;/span&gt;
      &lt;span class='hs-keyword'&gt;then&lt;/span&gt; &lt;span class='hs-varid'&gt;percentPos&lt;/span&gt; &lt;span class='hs-num'&gt;99&lt;/span&gt;
      &lt;span class='hs-keyword'&gt;else&lt;/span&gt; &lt;span class='hs-varid'&gt;percentPos&lt;/span&gt; &lt;span class='hs-num'&gt;1&lt;/span&gt;
  &lt;span class='hs-varid'&gt;return&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;heroinStatus&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-varid'&gt;testResult&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;

&lt;span class='hs-comment'&gt;-- Some handy distributions.&lt;/span&gt;
&lt;span class='hs-definition'&gt;percentUser&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-varid'&gt;percent&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt; &lt;span class='hs-conid'&gt;User&lt;/span&gt; &lt;span class='hs-conid'&gt;Clean&lt;/span&gt;
&lt;span class='hs-definition'&gt;percentPos&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-varid'&gt;percent&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt; &lt;span class='hs-conid'&gt;Pos&lt;/span&gt; &lt;span class='hs-conid'&gt;Neg&lt;/span&gt;

&lt;span class='hs-comment'&gt;-- A weighted distribution with two elements.&lt;/span&gt;
&lt;span class='hs-definition'&gt;percent&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt; &lt;span class='hs-varid'&gt;x1&lt;/span&gt; &lt;span class='hs-varid'&gt;x2&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt;
  &lt;span class='hs-varid'&gt;weighted&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;x1&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-varid'&gt;p&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;x2&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-num'&gt;100&lt;/span&gt;&lt;span class='hs-comment'&gt;-&lt;/span&gt;&lt;span class='hs-varid'&gt;p&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code is based our &lt;a href="http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions"&gt;FDist monad&lt;/a&gt;, which is in turn based on
&lt;a href="http://web.engr.oregonstate.edu/~erwig/pfp/"&gt;PFP&lt;/a&gt;.  Don&amp;#8217;t worry if it seems slightly mysterious; you can think of the
&amp;ldquo;&lt;code&gt;&amp;lt;-&lt;/code&gt;&amp;#8221; operator as choosing an element from a probability
distribution.&lt;/p&gt;

&lt;p&gt;Running our drug test shows every possible combination of the two
variables:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='hs-varop'&gt;&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;exact&lt;/span&gt; &lt;span class='hs-varid'&gt;drugTest1&lt;/span&gt;
&lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;User&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-conid'&gt;Pos&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-num'&gt;0.1&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;
 &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;User&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-conid'&gt;Neg&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-num'&gt;0.0&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;
 &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Clean&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-conid'&gt;Pos&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-num'&gt;1.0&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;
 &lt;span class='hs-conid'&gt;Perhaps&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Clean&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt;&lt;span class='hs-conid'&gt;Neg&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-num'&gt;98.9&lt;/span&gt;&lt;span class='hs-varop'&gt;%&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you look carefully, we have a problem.  Most of the employees who test
positive are actually clean!  Let&amp;#8217;s tweak our code a bit, and try to zoom
in on the positive test results.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 22 Feb 2007 18:11:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:fffdc914-d289-4ac8-bde5-7bbb02451aeb</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/02/22/bayes-rule-and-drug-tests</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <category>Probability</category>
      <category>Recommended</category>
      <category>ProbabilityMonads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/306</trackback:ping>
    </item>
    <item>
      <title>Refactoring probability distributions, part 2: Random sampling</title>
      <description>&lt;p&gt;In &lt;a href="http://www.randomhacks.net/articles/2007/02/21/refactoring-probability-distributions"&gt;Part 1&lt;/a&gt;, we cloned &lt;a href="http://web.engr.oregonstate.edu/~erwig/pfp/"&gt;PFP&lt;/a&gt;, a library for computing with probability distributions. PFP represents a distribution as a list of possible values, each with an associated probability.&lt;/p&gt;

&lt;p&gt;But in the real world, things aren&amp;#8217;t always so easy.  What if we wanted to pick  a random number between 0 and 1? Our previous implementation would break, because there&amp;#8217;s an infinite number of values between 0 and 1&amp;#8212;they don&amp;#8217;t exactly fit in a list.&lt;/p&gt;

&lt;p&gt;As it turns out, Sungwoo Park and colleagues found &lt;a href="http://citeseer.ist.psu.edu/752237.html"&gt;an elegant solution&lt;/a&gt; to this problem. They represented probability distributions as sampling functions, resulting in something called the &amp;lambda;&lt;sub&gt;&amp;#x25EF;&lt;/sub&gt; calculus. (I have no idea how to pronounce this!)&lt;/p&gt;

&lt;p&gt;With a little bit of hacking, we can use their sampling functions as a drop-in replacement for PFP.&lt;/p&gt;

&lt;h3&gt;A common interface&lt;/h3&gt;

&lt;p&gt;Since we will soon have two ways to represent probability distributions, we need to define a common interface.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='hs-keyword'&gt;type&lt;/span&gt; &lt;span class='hs-conid'&gt;Weight&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-conid'&gt;Float&lt;/span&gt;

&lt;span class='hs-keyword'&gt;class&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Functor&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Monad&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-conid'&gt;Dist&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyword'&gt;where&lt;/span&gt;
  &lt;span class='hs-varid'&gt;weighted&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;a&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Weight&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt;

&lt;span class='hs-definition'&gt;uniform&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;Dist&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-varid'&gt;a&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-varid'&gt;a&lt;/span&gt;
&lt;span class='hs-definition'&gt;uniform&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-varid'&gt;weighted&lt;/span&gt; &lt;span class='hs-varop'&gt;.&lt;/span&gt; &lt;span class='hs-varid'&gt;map&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;\&lt;/span&gt;&lt;span class='hs-varid'&gt;x&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-varid'&gt;x&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-num'&gt;1&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function &lt;code&gt;uniform&lt;/code&gt; will create an equally-weighted distribution from a list of values. Using this API, we can represent a two-child family as follows:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_haskell "&gt;&lt;span class='hs-keyword'&gt;data&lt;/span&gt; &lt;span class='hs-conid'&gt;Child&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-conid'&gt;Girl&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;|&lt;/span&gt; &lt;span class='hs-conid'&gt;Boy&lt;/span&gt;
  &lt;span class='hs-keyword'&gt;deriving&lt;/span&gt; &lt;span class='hs-layout'&gt;(&lt;/span&gt;&lt;span class='hs-conid'&gt;Show&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Eq&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Ord&lt;/span&gt;&lt;span class='hs-layout'&gt;)&lt;/span&gt;

&lt;span class='hs-definition'&gt;child&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;Dist&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-conid'&gt;Child&lt;/span&gt;
&lt;span class='hs-definition'&gt;child&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-varid'&gt;uniform&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Girl&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-conid'&gt;Boy&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;

&lt;span class='hs-definition'&gt;family&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;::&lt;/span&gt; &lt;span class='hs-conid'&gt;Dist&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='hs-varid'&gt;d&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-conid'&gt;Child&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
&lt;span class='hs-definition'&gt;family&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;=&lt;/span&gt; &lt;span class='hs-keyword'&gt;do&lt;/span&gt;
  &lt;span class='hs-varid'&gt;child1&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;child&lt;/span&gt;
  &lt;span class='hs-varid'&gt;child2&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='hs-varid'&gt;child&lt;/span&gt;
  &lt;span class='hs-varid'&gt;return&lt;/span&gt; &lt;span class='hs-keyglyph'&gt;[&lt;/span&gt;&lt;span class='hs-varid'&gt;child1&lt;/span&gt;&lt;span class='hs-layout'&gt;,&lt;/span&gt; &lt;span class='hs-varid'&gt;child2&lt;/span&gt;&lt;span class='hs-keyglyph'&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we need to implement this API two different ways: Once with lists, and a second time with sampling functions.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions"&gt;Read More&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 21 Feb 2007 23:53:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:48ce73c7-a197-4909-af77-6da8d71db1a8</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2007/02/21/randomly-sampled-distributions</link>
      <category>Haskell</category>
      <category>Math</category>
      <category>Monads</category>
      <category>Probability</category>
      <category>ProbabilityMonads</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/302</trackback:ping>
    </item>
  </channel>
</rss>

