<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
<title type="text">blog.gbacon.com</title>
<generator uri="https://github.com/mojombo/jekyll">Jekyll</generator>
<link rel="self" type="application/atom+xml" href="http://blog.gbacon.com/feed.xml" />
<link rel="alternate" type="text/html" href="http://blog.gbacon.com" />
<updated>2013-10-20T15:59:31-05:00</updated>
<id>http://blog.gbacon.com/</id>
<author>
  <name>Greg Bacon</name>
  <uri>http://blog.gbacon.com/</uri>
  <email>gbacon@gbacon.com</email>
</author>


<entry>
  <title type="html"><![CDATA[Net::OpenID::Consumer failure: naive verify failed network]]></title>
  <link>http://blog.gbacon.com/2011/05/netopenidconsumer-fails-with-naiveverifyfaile.html</link>
  <id>http://blog.gbacon.com/2011/05/netopenidconsumer-fails-with-naiveverifyfaile</id>
  <published>2011-05-23T00:00:00-05:00</published>
  <updated>2011-05-23T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;I was working on adding OpenID to a &lt;a href=&#39;http://mojolicious.org/&#39;&gt;Mojolicious&lt;/a&gt; webapp on &lt;a href=&#39;http://www.dotcloud.com/&#39;&gt;DotCloud&lt;/a&gt;—thanks to &lt;a href=&#39;http://groups.google.com/group/mojolicious/msg/42c75d993f485753&#39;&gt;helpful sample code&lt;/a&gt; from Henry that &lt;a href=&#39;http://search.cpan.org/~mart/Net-OpenID-Consumer-1.03/&#39;&gt;Net::OpenID::Consumer-1.03&lt;/a&gt;—and hit a strange failure. The call to &lt;code&gt;handle_server_response&lt;/code&gt; was failing in the &lt;code&gt;error&lt;/code&gt; callback with a generic error code &lt;code&gt;naive_verify_failed_network&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Going source diving, I learned slightly more about this particular error: “Could not contact provider to verify signature.” Details, man; I’m a fact finder! The good news is this particular error code is returned in a single place, at line 849:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;k&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$self&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;_fail&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;naive_verify_failed_network&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;unless&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$res&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$res&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;is_success&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here &lt;code&gt;$res&lt;/code&gt; is an &lt;a href=&#39;http://search.cpan.org/perldoc?HTTP::Response&#39;&gt;HTTP::Response&lt;/a&gt; instance returned from the &lt;code&gt;request&lt;/code&gt; method on &lt;a href=&#39;http://search.cpan.org/perldoc?LWPx::ParanoidAgent&#39;&gt;LWPx::ParanoidAgent&lt;/a&gt;. HTTP::Response has another helpful method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3 id=&#39;id1&#39;&gt;&lt;code&gt;$r-&amp;gt;error_as_HTML&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Returns a string containing a complete HTML document indicating what error occurred. This method should only be called when &lt;code&gt;$r-&amp;gt;is_error&lt;/code&gt; is TRUE.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I first do a little plumbing for my &lt;a href=&#39;http://search.cpan.org/perldoc?Mojolicious::Lite&#39;&gt;Mojolicious::Lite&lt;/a&gt; prototype.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$log&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;app&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;log&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;$SIG&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;__WARN__&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;sub &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
  &lt;span class=&#39;nb&#39;&gt;unshift&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$log&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
  &lt;span class=&#39;nb&#39;&gt;goto&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$log&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;can&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;warn&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Grungy, yes, but it’s a quick adaptation of a nicer technique for &lt;a href=&#39;https://github.com/kraih/mojo/wiki/Debugging-for-non-lite-apps#STDERR_Redirection_to_an_Application&amp;amp;#39;s_Log&#39;&gt;debugging non-lite apps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just before &lt;code&gt;return $self-&amp;gt;_fail ...&lt;/code&gt;, I added&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$res&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$res&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;is_error&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;warn&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$res&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;error_as_HTML&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After retrying the OpenID verification, my log contained&lt;/p&gt;
&lt;pre&gt;501 Attempt to reload LWPx/Protocol/https_paranoid.pm aborted&lt;/pre&gt;
&lt;p&gt;but running &lt;code&gt;grep -rl Attempt\ to\ reload ~/perl5/lib&lt;/code&gt; produced no hits.&lt;/p&gt;

&lt;p&gt;Same with Google.&lt;/p&gt;

&lt;p&gt;Chopping the specific bits out of my query, leaving “Attempt to reload” aborted, the first hit was a &lt;a href=&#39;http://search.cpan.org/~jesse/perl-5.14.0/pod/perldiag.pod#Attempt_to_reload_%s_aborted.&#39;&gt;perldiag entry&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3 id=&#39;attempt_to_reload_s_aborted&#39;&gt;Attempt to reload %s aborted.&lt;/h3&gt;

&lt;p&gt;(F) You tried to load a file with use or require that failed to compile once already. Perl will not try to compile this file again unless you delete its entry from &lt;code&gt;%INC&lt;/code&gt;. See &lt;code&gt;require&lt;/code&gt; in perlfunc and &lt;code&gt;%INC&lt;/code&gt; in perlvar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, so let’s see why the module is unhappy:&lt;/p&gt;
&lt;pre&gt;$ perl -Iperl5 -MLWPx::Protocol::https_paranoid -de 0

Loading DB routines from perl5db.pl version 1.33
Editor support available.

Enter h or `h h&#39; for help, or `man perldebug&#39; for more help.

Can&#39;t locate IO/Socket/SSL.pm in @INC at ...&lt;/pre&gt;
&lt;p&gt;Hidden dependency! &lt;a href=&#39;http://toroid.org/ams/etc/mojolicious-session-cookies&#39;&gt;IO::Socket::SSL is good to have with Mojolicious&lt;/a&gt;, so I edited my &lt;code&gt;Makefile.PL&lt;/code&gt; to include&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;n&#39;&gt;requires&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;IO::Socket::SSL&amp;quot;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;1.43&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A sequence of &lt;code&gt;perl Makefile.PL; make; dotcloud push ...&lt;/code&gt; gave me successful OpenID verification! As an extra goodie thanks to DotCloud, instead of a &lt;a href=&#39;http://search.cpan.org/perldoc?Cache::File&#39;&gt;Cache::File&lt;/a&gt; instead, my code uses &lt;a href=&#39;http://search.cpan.org/perldoc?Redis%C2%A0&#39;&gt;Redis&lt;/a&gt; in the &lt;code&gt;cache&lt;/code&gt; parameter to Net::OpenID::Consumer’s constructor.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2011/05/netopenidconsumer-fails-with-naiveverifyfaile.html&quot;&gt;Net::OpenID::Consumer failure: naive verify failed network&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on May 23, 2011.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Considering a gas-powered standby generator]]></title>
  <link>http://blog.gbacon.com/2011/04/considering-gas-powered-standby.html</link>
  <id>http://blog.gbacon.com/2011/04/considering-gas-powered-standby</id>
  <published>2011-04-29T00:00:00-05:00</published>
  <updated>2011-04-29T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;I’ve been wearing my &lt;a href=&#39;http://bowilliams.com/&#39;&gt;Bo Williams&lt;/a&gt; Risk Analysis™ cap a fair amount for the past couple of days, and this post started life as a comment on his post &lt;a href=&#39;http://bowilliams.com/2011/04/friday-miscellanea-post-alabama-tornado-super-outbreak-edition/&#39;&gt;Friday miscellanea, post-Alabama tornado super-outbreak edition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our house has gas heat and a gas set in the fireplace. I’ve been letting the latter slide in a state of disrepair. I recognize and accept this BWRA™ Demerit. It will be ready before winter 2011, which will mean redundant sources of heat. You ought to see my related &lt;a href=&#39;http://www.davidco.com/&#39;&gt;GTD&lt;/a&gt; project list!&lt;/p&gt;

&lt;p&gt;The option is obvious now, but it took a conversation with my dad to learn about permanent standby generators that run on natural gas and periodically test themselves. I priced them online and may be able to purchase a unit that would power most of my house, perhaps in staggered operation for heavy loads such as HVAC and dryer, for around $5k with no headaches of managing a gasoline reserve or just–in–time fuel purchases.&lt;/p&gt;

&lt;p&gt;The last week–long outage in the area was nearly forty years ago, but sidestepping even hours–long outages due to storms, ice on power lines, drunks hitting poles, and so on is awfully appealing too. I emptied the refrigerator and freezer, and temperatures in the Huntsville area are projected to be mild. My one power–related worry is my 55–gallon cichlid tank. I turned on a battery–powered air pump, but that’s about the best I could do. I think I was a week overdue for a water change when we lost power, so staying on top of aquarium chores in the future will help there too, assuming optimistically that these hardy critters make it.&lt;/p&gt;

&lt;p&gt;Other questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where can I find comprehensive lists of electrical and gas outages to find whether I’m trading more–or–less equivalent problems?&lt;/li&gt;

&lt;li&gt;How expensive would backup mode be?&lt;/li&gt;

&lt;li&gt;Fossil fuels in general aren’t getting any cheaper, so at what gas price does such a generator become a total dud?&lt;/li&gt;

&lt;li&gt;What about purification of, say, rain water?&lt;/li&gt;

&lt;li&gt;I expect a crazy run on generators when we’re no longer part of the third world. What are good value metrics?&lt;/li&gt;

&lt;li&gt;What other issues do I need to consider?&lt;/li&gt;
&lt;/ul&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2011/04/considering-gas-powered-standby.html&quot;&gt;Considering a gas-powered standby generator&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on April 29, 2011.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Extracting comma-separated integers with Perl]]></title>
  <link>http://blog.gbacon.com/2011/03/extracting-comma-separated-integers.html</link>
  <id>http://blog.gbacon.com/2011/03/extracting-comma-separated-integers</id>
  <published>2011-03-01T00:00:00-06:00</published>
  <updated>2011-03-01T00:00:00-06:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;A friend writes asking which of&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;my @data = ( $data =~ m|(-?\d+),(-?\d+),(\-?\d+)\r| );&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;($data) = (split &amp;quot;\r&amp;quot;, $data);
my @data = split &amp;#39;,&amp;#39;, $data;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;would be better for extracting integers from a line of input, and my reply is below.&lt;/p&gt;

&lt;p&gt;The best approach depends on a few factors. Who generates the data you’re processing? How much slop in the input format do you need to accommodate? How flexible do you need to be with respect to future changes in the input, &lt;em&gt;e.g.&lt;/em&gt;, extra fields, different types, and so on?&lt;/p&gt;

&lt;p&gt;The CR (&lt;code&gt;\r&lt;/code&gt;) in your input is a red flag. Are you running on a Unix platform with input generated on Windows? Can you be more specific about “possibly some other stuff” after the comma-separated numbers?&lt;/p&gt;

&lt;p&gt;Perl’s &lt;a href=&#39;http://perldoc.perl.org/perlvar.html#%24/&#39;&gt;&lt;code&gt;$/&lt;/code&gt; special variable&lt;/a&gt; can handle oddball line endings. Its default value varies with what makes sense for the current platform: &lt;em&gt;e.g.&lt;/em&gt;, &lt;code&gt;\n&lt;/code&gt; on Unix and &lt;code&gt;\r\n&lt;/code&gt; on Windows. Macs introduce another twist (see &lt;a href=&#39;http://perldoc.perl.org/perlport.html#Newlines&#39;&gt;Newlines in the perlport documentation&lt;/a&gt;), but I assume you’re not using that platform.&lt;/p&gt;

&lt;p&gt;On Windows for files opened in text mode (the default), the C library silently transforms CR followed by LF into LF, so if this matches your setup, I’m surprised you’re seeing the &lt;code&gt;\r&lt;/code&gt; at all.&lt;/p&gt;

&lt;p&gt;Say your input is plain text generated on Windows, and you’re running on Linux. Then you’d process it with code of the form&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;vg&#39;&gt;$/&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;\r\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
 
&lt;span class=&#39;k&#39;&gt;while&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;defined&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$data&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;chomp&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;o&#39;&gt;...&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Remember that &lt;a href=&#39;http://perldoc.perl.org/functions/chomp.html&#39;&gt;&lt;code&gt;chomp&lt;/code&gt;&lt;/a&gt; removes the value of &lt;code&gt;$/&lt;/code&gt; from the end of the target.&lt;/p&gt;

&lt;p&gt;As for extracting the data, &lt;a href=&#39;http://www.stonehenge.com/merlyn/&#39;&gt;Randal Schwartz&lt;/a&gt; (author of &lt;em&gt;&lt;a href=&#39;http://oreilly.com/catalog/9780596520113&#39;&gt;Learning Perl&lt;/a&gt;&lt;/em&gt;, a.k.a. the llama book) has a rule of thumb:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use capturing or &lt;code&gt;m//g&lt;/code&gt; when you know what you want to &lt;strong&gt;keep&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;split&lt;/code&gt; when you know what you want to &lt;strong&gt;throw away&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I first saw this useful guideline in &lt;a href=&#39;http://perl.plover.com/yak/regex/samples/slide070.html&#39;&gt;Regular Expression Mastery&lt;/a&gt; by Mark Dominus.&lt;/p&gt;

&lt;p&gt;If this is a quick-and-dirty utility, I’d be inclined to write&lt;/p&gt;

&lt;p&gt;&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;nv&#39;&gt;@data&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;split&lt;/span&gt; &lt;span class=&#39;sr&#39;&gt;/\s*,\s*/&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$data&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;This allows for and removes any whitespace around the commas.&lt;/p&gt;

&lt;p&gt;If it’s important to nail down the format (maybe as a sanity check that you’re in the section of the config file where you think you are), you could write&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$data&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=~&lt;/span&gt;&lt;span class=&#39;sr&#39;&gt; /^\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*(-?\d+)\s*$/&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$y&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$z&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$2&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$3&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
    &lt;span class=&#39;o&#39;&gt;...&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;die&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$0: $ARGV:$.: unexpected format&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the use of &lt;code&gt;$1&lt;/code&gt; and friends inside the conditional only. Always, &lt;em&gt;always&lt;/em&gt;, &lt;strong&gt;always&lt;/strong&gt; protect uses of capture variables with conditionals.&lt;/p&gt;

&lt;p&gt;The pattern is just at the annoyance threshold of repetition and illegibility. Perl version 5.10 opens up nice possibilities with &lt;a href=&#39;http://perldoc.perl.org/perlre.html#Capture-buffers&#39;&gt;named capture buffers&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;c1&#39;&gt;#! /usr/bin/env perl&lt;/span&gt;
 
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;strict&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;warnings&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
 
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;mf&#39;&gt;5.10.0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
 
&lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$record&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;sx&#39;&gt;qr/&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    ^&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    (?&amp;amp;ws)&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    (?&amp;lt;num&amp;gt;(?&amp;amp;n)) (?&amp;amp;sep) (?&amp;lt;num&amp;gt;(?&amp;amp;n)) (?&amp;amp;sep) (?&amp;lt;num&amp;gt;(?&amp;amp;n))&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    (?&amp;amp;ws)&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    $&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt; &lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    (?(DEFINE)&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;        (?&amp;lt;n&amp;gt; -? \d+)&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;        (?&amp;lt;ws&amp;gt; \s* )&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;        (?&amp;lt;sep&amp;gt; (?&amp;amp;ws) , (?&amp;amp;ws))&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;    )&lt;/span&gt;
&lt;span class=&#39;sx&#39;&gt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
 
&lt;span class=&#39;k&#39;&gt;while&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sr&#39;&gt;&amp;lt;DATA&amp;gt;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sr&#39;&gt;/$record/&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$y&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$z&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;vg&#39;&gt;$-&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;num&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;};&lt;/span&gt;
        &lt;span class=&#39;k&#39;&gt;print&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;got: x=$x, y=$y, z=$z\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;warn&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$0: line $.: no match\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
 
&lt;span class=&#39;bp&#39;&gt;__DATA__&lt;/span&gt;
&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;3&lt;/span&gt;
&lt;span class=&#39;mi&#39;&gt;4&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;5&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;6&lt;/span&gt;
&lt;span class=&#39;mi&#39;&gt;7&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Its output:&lt;/p&gt;
&lt;pre&gt;got: x=1, y=2, z=3
got: x=4, y=5, z=6
./prog: line 3: no match&lt;/pre&gt;
&lt;p&gt;Notice its use of &lt;a href=&#39;http://perldoc.perl.org/perlvar.html#%25-&#39;&gt;the special &lt;code&gt;%-&lt;/code&gt; hash&lt;/a&gt; that records all captures named “num” in this case. With &lt;a href=&#39;http://perldoc.perl.org/perlre.html#%28DEFINE%29&#39;&gt;&lt;code&gt;(DEFINE)&lt;/code&gt;&lt;/a&gt;, subpatterns get meaningful names, and the &lt;code&gt;/x&lt;/code&gt; modifier allow for judicious use of whitespace inside the pattern.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2011/03/extracting-comma-separated-integers.html&quot;&gt;Extracting comma-separated integers with Perl&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on March 01, 2011.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Checkers game-over in Haskell]]></title>
  <link>http://blog.gbacon.com/2011/01/checkers-game-over-in-haskell.html</link>
  <id>http://blog.gbacon.com/2011/01/checkers-game-over-in-haskell</id>
  <published>2011-01-01T00:00:00-06:00</published>
  <updated>2011-01-01T00:00:00-06:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;The programming subreddit recently had a discussion about &lt;a href=&#39;http://www.reddit.com/r/compsci/comments/esbpe/anyone_have_a_good_algorithm_for_checking_the/&#39;&gt;testing a checkers board for game-over&lt;/a&gt;. I wondered how specifying the rules for legal moves would look with &lt;a href=&#39;http://haskell.org/tutorial/patterns.html&#39;&gt;Haskell’s pattern matching&lt;/a&gt;, and this post is a study of that technique. In fact, you can run yourself. Copy-and-paste the post body to a file named &lt;code&gt;Checkers.lhs&lt;/code&gt; to get a working program!&lt;/p&gt;

&lt;p&gt;The game is &lt;a href=&#39;http://en.wikipedia.org/wiki/English_draughts&#39;&gt;American checkers&lt;/a&gt; or English draughts, played on an eight–by–eight checkerboard, of all surfaces.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;cm&#39;&gt;{-# LANGUAGE ViewPatterns #-}&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;module&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Checkers&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.Char&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;toLower&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;toUpper&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.List&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;tails&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;transpose&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Test.HUnit&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;data&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;deriving&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Show&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a rough idea of the punchline, I was hoping for code along the lines of&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and eventually&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;gameOver&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Bool&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;gameOver&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;blueMoves&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;||&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;whiteMoves&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The OP on reddit chose white and blue for the sides’ colors, and above we have more–or–less declarative rules for legal white moves. A pawn or king (&lt;code&gt;w&lt;/code&gt; and &lt;code&gt;W&lt;/code&gt; respectively) can move to an empty space before it. Kings are special in that they can move backwards. The list ends with legal jumps, and everything else is invalid.&lt;/p&gt;

&lt;p&gt;The code is repetitive, but I’ll clean that up later.&lt;/p&gt;

&lt;p&gt;An immediate problem is the patterns are linear, but all legal moves in checkers are along diagonals. I kicked around ideas such as using &lt;a href=&#39;http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Arrays&#39;&gt;IArray&lt;/a&gt; or nasty double-applications of &lt;a href=&#39;http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v%3A-33--33-&#39;&gt;&lt;code&gt;!!&lt;/code&gt;&lt;/a&gt;. Then I realized I could rotate the board by 45° with a shear, a transposition, and removal of placeholders.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;c1&#39;&gt;-- diagonals with positive slopes&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;posdiags&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reverse&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;used&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;transpose&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zip&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;..&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;              &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt;
                      &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;*&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;used&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;not&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;all&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;#.&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Getting the other diagonals is similar, but again brings too much repetition.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;negdiags&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reverse&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;used&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;transpose&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zip&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;..&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt;
                      &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;              &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;*&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;used&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;not&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;all&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;#.&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;pre&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;div&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;div&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Having &lt;code&gt;Board&lt;/code&gt; values to play with is trivial:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;board&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;let&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;bs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;splitAt&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;a&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;bs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It chops one long string into rows, but with Haskell’s usually–awkward multiline strings, it’s not so bad. For example&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;startBoard&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
  &lt;span class=&#39;s&#39;&gt;&amp;quot;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;b.b.b.b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w.w.w.w.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.w.w.w.w&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;  \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w.w.w.w.&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An early cut at &lt;code&gt;blueMoves&lt;/code&gt; and reducing the repetition in the rules for moves was&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;blueMoves&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;blueMoves&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;diagonals&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;sum&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;concatMap&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tails&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Bb&amp;quot;&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Ww&amp;quot;&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Ww&amp;quot;&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;move&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sticking with the theme of repetition, &lt;code&gt;whiteMoves&lt;/code&gt; is nearly identical with little breadcrumbs of differences. That was all good because I wanted to have a testsuite before I started refactoring.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;tests&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Test&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;tests&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;test&lt;/span&gt;
  &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;assertEqual&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;white must have piece to move&amp;quot;&lt;/span&gt;
      &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;nw&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;b.b.b.b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;se&#39;&gt;            \&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;nw&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;whiteMoves&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;board&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not bad for a start, but each testcase will have a dual for the other side—way too much copy-and-paste.&lt;/p&gt;
&lt;pre&gt;*Checkers&gt; runTestTT tests
Loading package HUnit-1.2.2.1 ... linking ... done.
Cases: 1  Tried: 1  Errors: 0  Failures: 0
Counts {cases = 1, tried = 1, errors = 0, failures = 0}&lt;/pre&gt;
&lt;p&gt;Whee!&lt;/p&gt;

&lt;p&gt;To wring out the duplication in the code for each side’s moves, I considered using &lt;a href=&#39;http://www.haskell.org/haskellwiki/Template_Haskell&#39;&gt;Template Haskell&lt;/a&gt;—a cousin of Lisp macros for Haskell. I decided to push lexical closures as far as I could, and the result is below.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;blueMoves&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;whiteMoves&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;blueMoves&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;whiteMoves&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;let&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;blueOrder&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;id&lt;/span&gt;  &lt;span class=&#39;c1&#39;&gt;-- diagonals emerge in blue’s perspective&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;whiteOrder&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reverse&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;count&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;direction&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;side&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;diagonals&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ds&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sum&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;concatMap&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tails&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;direction&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ds&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;     &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;same&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;     &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;king&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;o&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;same&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;opponent&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;o&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;o&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;king&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;opponent&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;o&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sideCanMove&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;same&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;piece&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toLower&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toLower&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;side&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;opponent&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;piece&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toLower&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;/=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toLower&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;side&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;king&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;  &lt;span class=&#39;n&#39;&gt;same&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt;         &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toUpper&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;side&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;               &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;piece&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;    &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;BbWw&amp;quot;&lt;/span&gt;  &lt;span class=&#39;c1&#39;&gt;-- filter empty spaces&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;count&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;blueOrder&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;whiteOrder&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;pre&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;div&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;div&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code in &lt;code&gt;count&lt;/code&gt; (notice the &lt;a href=&#39;http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns&#39;&gt;view pattern&lt;/a&gt;?) is a skeleton to be customized for the blue side and the white side, and it distills the repeated code. The definition of &lt;code&gt;sideCanMove&lt;/code&gt; generalizes the rules for legal moves on either side. We have to reverse the diagonals to make them usable on the white side.&lt;/p&gt;

&lt;p&gt;To get both sets of diagonals, the only difference is how to shear the board: bottom-away for positive slopes and top-away for negative.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;c1&#39;&gt;-- positive slopes slice from NW to SE&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;c1&#39;&gt;-- negative slopes slice from SW to NE&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;c1&#39;&gt;-- both extend in blue’s direction (north-to-south)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;diagonals&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;diagonals&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Board&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;rows&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;positiveSlopes&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;rows&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;negativeSlopes&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;rows&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;positiveSlopes&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;negativeSlopes&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;i&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;k&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;*&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;size&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;used&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;not&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;all&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ignored&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;order&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;not&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;null&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                  &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;not&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ignored&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                  &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;transpose&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                  &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;order&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                  &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zip&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;..&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;ignored&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;elem&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;#.&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;shear&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;l&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;r&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;l&lt;/span&gt; &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;replicate&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;r&lt;/span&gt; &lt;span class=&#39;sc&#39;&gt;&amp;#39;#&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally come the tests that I added as I went. To factor out duplication, each board becomes two testcases. The first is as–is, and the same condition should hold for the other side. See the definition of &lt;code&gt;invert&lt;/code&gt; in the &lt;code&gt;where&lt;/code&gt; clause.&lt;/p&gt;

&lt;p&gt;I had hoped for a more elegant result, but it was an interesting exercise and a fun problem!&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;tests&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Test&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;tests&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;test&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;concat&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;must have piece to move&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;b.b.b.b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.b.b.b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;one move&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w. . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;one king move&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;W. . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;two moves&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; .w. . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;king can move back from end&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;2&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . .W. &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;can jump opponent pawn&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.b. . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w. . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;can&amp;#39;t jump blocked opponent&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; .b. . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.b. . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w. . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;can jump opponent king&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;.B. . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;w. . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;king can jump trailing opponent&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . .W&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . .b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;king can&amp;#39;t jump protected opponent&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . .W&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . .b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . .b. &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;king can&amp;#39;t jump onto own piece&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . .W&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . .b.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . .w. &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;king has four moves&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;4&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . .W. .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;cannot displace opponent on king row&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. . .b.b&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . .w.&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;. . . . &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;s&#39;&gt; . . . .&amp;quot;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;nw&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;whiteMoves&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;board&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;nb&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;blueMoves&lt;/span&gt;  &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;board&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;checkMoves&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;name&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;expect&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;           &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;assertEqual&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;white: &amp;quot;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;name&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;expect&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;nw&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;           &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;assertEqual&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;blue: &amp;quot;&lt;/span&gt;  &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;name&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;expect&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;nb&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;invert&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;           &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;invert&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reverse&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;replace&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;W&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;         &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;replace&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tbl&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;c&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;maybe&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;c&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;id&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;lookup&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;c&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tbl&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2011/01/checkers-game-over-in-haskell.html&quot;&gt;Checkers game-over in Haskell&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on January 01, 2011.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Perl: conditional use and scope]]></title>
  <link>http://blog.gbacon.com/2010/03/perl-conditional-use-and-scope.html</link>
  <id>http://blog.gbacon.com/2010/03/perl-conditional-use-and-scope</id>
  <published>2010-03-01T00:00:00-06:00</published>
  <updated>2010-03-01T00:00:00-06:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;A reader asks&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I conditionally load a perl module, do those module variables get passed to the whole perl script?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if ( some_test ) {
  use &amp;quot;perlmodule_001&amp;quot;;
}
else {
  use &amp;quot;perlmodule_002&amp;quot;;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Are the elements of either perl module available outside the &lt;code&gt;if&lt;/code&gt; statement?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main program from the question has a syntax error:&lt;/p&gt;
&lt;pre&gt;syntax error at prog0 line 2, near &quot;use &quot;perlmodule_001&quot;&quot;&lt;/pre&gt;
&lt;p&gt;Perl’s &lt;a href=&#39;http://perldoc.perl.org/functions/use.html&#39;&gt;documentation for &lt;code&gt;use&lt;/code&gt;&lt;/a&gt; explains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;use Module&lt;/strong&gt;&lt;br /&gt;Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;BEGIN { require Module; Module-&amp;gt;import( LIST ); }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;except that Module &lt;em&gt;must&lt;/em&gt; be a bareword.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note the bareword constraint at the end: the compiler doesn’t like the double quotes around the argument to &lt;code&gt;use&lt;/code&gt;. Our friend was likely thinking of the older &lt;a href=&#39;http://perldoc.perl.org/functions/require.html&#39;&gt;&lt;code&gt;require&lt;/code&gt;&lt;/a&gt; operator that &lt;em&gt;does&lt;/em&gt; accept strings and arbitrary expressions in general.&lt;/p&gt;

&lt;p&gt;Say we have two modules with alternative definitions of &lt;code&gt;$Foo&lt;/code&gt; and &lt;code&gt;$Bar&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;nb&#39;&gt;package&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_001&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Exporter&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;import&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@EXPORT&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;sx&#39;&gt;qw/ $Foo $Bar /&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$Foo&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$Bar&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;nb&#39;&gt;package&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_002&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Exporter&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;import&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@EXPORT&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;sx&#39;&gt;qw/ $Foo $Bar /&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$Foo&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;42&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;our&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$Bar&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;#39;w00t!&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the use of &lt;code&gt;Perlmodule_001&lt;/code&gt;, for example, rather than &lt;code&gt;perlmodule_001&lt;/code&gt;: the &lt;a href=&#39;http://perldoc.perl.org/perlmodlib.html&#39;&gt;perlmodlib documentation&lt;/a&gt; notes, “Perl informally reserves lowercase module names for pragma modules like &lt;a href=&#39;http://perldoc.perl.org/integer.html&#39;&gt;&lt;code&gt;integer&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#39;http://perldoc.perl.org/strict.html&#39;&gt;&lt;code&gt;strict&lt;/code&gt;&lt;/a&gt;.”&lt;/p&gt;

&lt;p&gt;Consider the following simple driver:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;c1&#39;&gt;#! /usr/bin/perl&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;warnings&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;strict&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;@ARGV&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$ARGV&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;eq&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;two&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_002&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_001&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;sub &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;maybeUndef&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;defined&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;?&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;&amp;lt;undefined&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;c1&#39;&gt;# got 5.10?&lt;/span&gt;
    &lt;span class=&#39;c1&#39;&gt;# $_[0] // &amp;quot;&amp;lt;undefined&amp;gt;&amp;quot;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;print&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Foo = &amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;maybeUndef&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$Foo&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;
      &lt;span class=&#39;s&#39;&gt;&amp;quot;Bar = &amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;maybeUndef&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$Bar&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It uses &lt;code&gt;maybeUndef&lt;/code&gt; to explicitly show when a value is undefined and also to silence potential undefined-value warnings.&lt;/p&gt;

&lt;p&gt;The program seems to run as intended&lt;/p&gt;
&lt;pre&gt;$ ./prog1
Foo = apple
Bar = orange&lt;/pre&gt;
&lt;p&gt;but the output is the same even when an argument of &lt;code&gt;two&lt;/code&gt; is supplied on the command line!&lt;/p&gt;
&lt;pre&gt;$ ./prog1 two
Foo = apple
Bar = orange&lt;/pre&gt;
&lt;p&gt;The good news is that the imported variables are in scope for the rest of the program, as indicated in the above documentation for &lt;code&gt;use&lt;/code&gt; (with emphasis added):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imports some semantics &lt;em&gt;into the current package&lt;/em&gt; from the named module &amp;#8230;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand why we never see &lt;code&gt;Perlmodule_002&lt;/code&gt;’s &lt;code&gt;$Foo&lt;/code&gt; and &lt;code&gt;$Bar&lt;/code&gt;, note that &lt;code&gt;use&lt;/code&gt; “is exactly equivalent to” &lt;code&gt;require&lt;/code&gt; at &lt;a href=&#39;http://perldoc.perl.org/perlmod.html#BEGIN%2C-UNITCHECK%2C-CHECK%2C-INIT-and-END&#39;&gt;&lt;code&gt;BEGIN&lt;/code&gt;&lt;/a&gt; time, and the perlmod documentation explains exactly when that is (with added emphasis):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;code&gt;BEGIN&lt;/code&gt; code block is executed as soon as possible, that is, the moment it is completely defined, &lt;em&gt;even before the rest of the containing file (or string) is parsed&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the compiler sees &lt;code&gt;use Perlmodule_002&lt;/code&gt; and processes it. Then it sees &lt;code&gt;use Perlmodule_001&lt;/code&gt; and processes it. When the compiler finishes digesting the rest of the code, it’s time for the execution phase, when the &lt;code&gt;@ARGV&lt;/code&gt; check finally takes place. As written, &lt;code&gt;Perlmodule_001&lt;/code&gt; will always win!&lt;/p&gt;

&lt;p&gt;Because ordinary modules affect the current package, &lt;code&gt;use&lt;/code&gt;–ing an ordinary module inside a conditional block is entirely misleading. I was careful to qualify the previous statement for ordinary modules because the effects of some pragmatic modules (&lt;em&gt;e.g.&lt;/em&gt;, &lt;code&gt;strict&lt;/code&gt; and &lt;code&gt;integer&lt;/code&gt;—note the lowercase names!) are limited tightly to the enclosing block only.&lt;/p&gt;

&lt;p&gt;The fix is to process &lt;code&gt;@ARGV&lt;/code&gt; at &lt;code&gt;BEGIN&lt;/code&gt; time and conditionalize the module imports with the equivalent &lt;code&gt;require&lt;/code&gt; and &lt;code&gt;import&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;c1&#39;&gt;#! /usr/bin/perl&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;warnings&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;strict&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;BEGIN&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;@ARGV&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$ARGV&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;eq&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;two&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;require&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_002&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;Perlmodule_002&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;import&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;require&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;Perlmodule_001&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;Perlmodule_001&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;import&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;sub &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;maybeUndef&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;defined&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;?&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;&amp;lt;undefined&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;c1&#39;&gt;# got 5.10?&lt;/span&gt;
    &lt;span class=&#39;c1&#39;&gt;# $_[0] // &amp;quot;&amp;lt;undefined&amp;gt;&amp;quot;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;print&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Foo  = &amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;maybeUndef&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$Foo&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;
      &lt;span class=&#39;s&#39;&gt;&amp;quot;Bar  = &amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;maybeUndef&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$Bar&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An alternative is protecting &lt;code&gt;use&lt;/code&gt; with &lt;a href=&#39;http://perldoc.perl.org/functions/eval.html&#39;&gt;&lt;code&gt;eval&lt;/code&gt;&lt;/a&gt; as in&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;k&#39;&gt;BEGIN&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;@ARGV&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$ARGV&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;eq&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;two&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;eval&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;use Perlmodule_002&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
    &lt;span class=&#39;c1&#39;&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;so a particular &lt;code&gt;use&lt;/code&gt; runs only when control reaches its &lt;code&gt;eval&lt;/code&gt; but is ignored otherwise. This is a safe, sensible use of &lt;code&gt;eval&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Either way, the program now does what we expect!&lt;/p&gt;
&lt;pre&gt;$ ./prog2
Foo  = apple
Bar  = orange
$ ./prog2 two
Foo  = 42
Bar  = w00t!&lt;/pre&gt;
&lt;p&gt;You might wonder why the code has to be inside a &lt;code&gt;BEGIN&lt;/code&gt; block after the &lt;code&gt;use&lt;/code&gt; lines are conditionalized. If you have the &lt;code&gt;strict&lt;/code&gt; pragma enabled—and you should!—it wants variables to be imported and declared before execution begins. Otherwise, compilation will fail because for all it knows, &lt;code&gt;$Foo&lt;/code&gt; and &lt;code&gt;$Bar&lt;/code&gt; in the &lt;code&gt;main&lt;/code&gt; package were typos.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2010/03/perl-conditional-use-and-scope.html&quot;&gt;Perl: conditional use and scope&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on March 01, 2010.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Finding duplicates with Perl and Haskell]]></title>
  <link>http://blog.gbacon.com/2009/08/finding-duplicates-with-perl-and.html</link>
  <id>http://blog.gbacon.com/2009/08/finding-duplicates-with-perl-and</id>
  <published>2009-08-31T00:00:00-05:00</published>
  <updated>2009-08-31T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;A coworker wanted to check a family of log files to be sure that a given task never appeared on multiple nodes at the same time. Log entries are on single, whitespace-separated lines, and the last field records a task’s start time, &lt;em&gt;e.g.&lt;/em&gt;,&lt;/p&gt;
&lt;pre&gt;1251475056672590000_1732248586_4&lt;/pre&gt;
&lt;p&gt;Of the three underscore–separated fields, the first is a timestamp, the second we don’t care about, and the third is a task identifier.&lt;/p&gt;

&lt;p&gt;This task is straightforward with Perl. The diamond operator (or &lt;a href=&#39;http://perldoc.perl.org/perlop.html#I/O-Operators&#39;&gt;null filehandle, as described in the “I/O Operators” section of the perlop manpage&lt;/a&gt;) takes care of the boilerplate for iterating over the paths on the command line, opening them, and reading each line. The scalar &lt;code&gt;$ARGV&lt;/code&gt; contains the name of the current file.&lt;/p&gt;

&lt;p&gt;By default, &lt;a href=&#39;http://perldoc.perl.org/functions/split.html&#39;&gt;&lt;code&gt;split&lt;/code&gt;&lt;/a&gt; separates fields by whitespace, so &lt;code&gt;(split)[-1]&lt;/code&gt; gives us the last field, from which we then grab the time and task with a regular expression and record its presence by &lt;a href=&#39;http://perldoc.perl.org/functions/push.html&#39;&gt;pushing&lt;/a&gt; the entry’s path and line number onto an array associated with that time/task pair. After we’ve processed the logs, these arrays should all be singletons.&lt;/p&gt;

&lt;p&gt;The continue clause is a little weird but necessary because the &lt;a href=&#39;http://perldoc.perl.org/perlvar.html#%24.&#39;&gt;special variable &lt;code&gt;$.&lt;/code&gt;&lt;/a&gt;, the current line number, does not reset on &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;’s implicit opens. &lt;code&gt;ARGV&lt;/code&gt; is a handle on the file being read.&lt;/p&gt;

&lt;p&gt;With this data structure, detecting duplicates is a search for time/task pairs with multiple hits. We count duplicates and let the user know what we found.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;perl&#39;&gt;&lt;span class=&#39;c1&#39;&gt;#! /usr/bin/perl&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;warnings&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;use&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;strict&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;c1&#39;&gt;# e.g., $hits = @{ $seen{$time}{$task} };&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;%seen&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;sub &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;num&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$a&lt;/span&gt; &lt;span class=&#39;sr&#39;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$b&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;while&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;split&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)[&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;-&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=~&lt;/span&gt;&lt;span class=&#39;sr&#39;&gt; /^(\d+)_\d+_(\d+)$/&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$time&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$2&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;push&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$seen&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$time&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}{&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$ARGV:$.&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;die&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$0: $ARGV:$.: bad timestamp/task field\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;continue&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;nb&#39;&gt;close&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ARGV&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;eof&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$duplicates&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;foreach&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$time&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;num&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;keys&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;%seen&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
    &lt;span class=&#39;k&#39;&gt;foreach&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$task&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nb&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;num&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;keys&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;%&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$seen&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$time&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;})&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
        &lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@hits&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$seen&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$time&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}{&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;$task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;};&lt;/span&gt;
        &lt;span class=&#39;k&#39;&gt;next&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@hits&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

        &lt;span class=&#39;nv&#39;&gt;$duplicates&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;+=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@hits&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
        &lt;span class=&#39;nb&#39;&gt;warn&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$0: duplicates for time=$time, task=$task:\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;
             &lt;span class=&#39;nb&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;    - $_\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;@hits&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
    &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;my&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$s&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$duplicates&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;?&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;s&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;span class=&#39;k&#39;&gt;print&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;$0: $duplicates duplicate$s detected.\n&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

&lt;span class=&#39;nb&#39;&gt;exit&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;$duplicates&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;?&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For comparison, I implemented the same log checker in Haskell. The function &lt;code&gt;allInputs&lt;/code&gt; emulates Perl’s diamond operator, and instead of a multi–level hash, the association is more direct: time/task pair to a list of hits.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;kr&#39;&gt;module&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Main&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;

&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Control.Monad&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;liftM&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.List&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;sort&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.Map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;empty&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;filter&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;fromListWith&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;toList&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;unionWith&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Prelude&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;hiding&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;filter&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;System.Environment&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;getArgs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;getProgName&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;System.Exit&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;ExitCode&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;..&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;exitWith&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Text.Printf&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;printf&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;kr&#39;&gt;type&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Time&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;type&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Task&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;data&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Duplicates&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
   &lt;span class=&#39;kt&#39;&gt;Duplicates&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;{&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;timestamp&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Time&lt;/span&gt;
              &lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;taskId&lt;/span&gt;    &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Task&lt;/span&gt;
              &lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;locations&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;FilePath&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)]&lt;/span&gt;
              &lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;main&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;IO&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;()&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;main&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt;
    &lt;span class=&#39;n&#39;&gt;logs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;allInputs&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;let&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;multi&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;dups&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;logs&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sum&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;subtract&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;length&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;locations&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;multi&lt;/span&gt;
     &lt;span class=&#39;n&#39;&gt;mapM_&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;msg&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;lines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;dupmsg&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;multi&lt;/span&gt;
     &lt;span class=&#39;n&#39;&gt;msg&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ndups&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;
     &lt;span class=&#39;n&#39;&gt;exitWith&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;0&lt;/span&gt;
                &lt;span class=&#39;kr&#39;&gt;then&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;ExitSuccess&lt;/span&gt;
                &lt;span class=&#39;kr&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;ExitFailure&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;msg&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;info&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;me&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getProgName&lt;/span&gt;
                      &lt;span class=&#39;n&#39;&gt;putStrLn&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;me&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;head&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;info&lt;/span&gt;
                      &lt;span class=&#39;n&#39;&gt;mapM_&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;putStrLn&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tail&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;

        &lt;span class=&#39;n&#39;&gt;ndups&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;1 duplicate detected&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;ndups&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;show&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot; duplicates detected&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;

        &lt;span class=&#39;n&#39;&gt;dupmsg&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Duplicates&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;task&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ls&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;unlines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;
            &lt;span class=&#39;n&#39;&gt;printf&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;duplicates for time=%s, task=%s:&amp;quot;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;task&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;
            &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;printf&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;    - %s:%d&amp;quot;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ls&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;allInputs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;IO&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;FilePath&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)]&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;allInputs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getArgs&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:[]&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(,)&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;-&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;`&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;liftM&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;`&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getContents&lt;/span&gt;
           &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;mapM&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;readFile&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fs&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zip&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fs&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;dups&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;FilePath&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Duplicates&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;dups&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;ds&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Duplicates&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;task&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ds&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt;
       &lt;span class=&#39;n&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt;
       &lt;span class=&#39;n&#39;&gt;toList&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt;
       &lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;length&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt;
       &lt;span class=&#39;n&#39;&gt;foldl&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;unionWith&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;++&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;empty&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt;
       &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;\&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;contents&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt;
              &lt;span class=&#39;n&#39;&gt;fromListWith&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;++&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;
              &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;wrap&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getTimeTask&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;
              &lt;span class=&#39;n&#39;&gt;zip&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;..&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;lines&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;contents&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;wrap&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;),&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)])&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;getTimeTask&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Time&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Task&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;getTimeTask&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tsk&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;
        &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tm&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;tsk&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;splitBy&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;&amp;#39;_&amp;#39;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;last&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;words&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;

        &lt;span class=&#39;n&#39;&gt;splitBy&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Eq&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;a&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;a&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]]&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;splitBy&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;splitBy&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;h&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;splitBy&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;t&lt;/span&gt;
            &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;h&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;rest&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;break&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;
                  &lt;span class=&#39;n&#39;&gt;t&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;drop&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;rest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/08/finding-duplicates-with-perl-and.html&quot;&gt;Finding duplicates with Perl and Haskell&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on August 31, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Immanuel]]></title>
  <link>http://blog.gbacon.com/2009/08/blog-post.html</link>
  <id>http://blog.gbacon.com/2009/08/blog-post</id>
  <published>2009-08-16T00:00:00-05:00</published>
  <updated>2009-08-16T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;For a child will be born to us, a son will be given to us;&lt;br /&gt;   And the government will rest on His shoulders;&lt;br /&gt;   And His name will be called Wonderful Counselor, Mighty God,&lt;br /&gt;   Eternal Father, Prince of Peace.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#39;http://www.biblegateway.com/passage/?book_id=29&amp;amp;chapter=9&amp;amp;version=49&#39;&gt;Isaiah 9:6&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/08/blog-post.html&quot;&gt;Immanuel&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on August 16, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[git: shrinking Subversion import]]></title>
  <link>http://blog.gbacon.com/2009/08/git-shrinking-subversion-import.html</link>
  <id>http://blog.gbacon.com/2009/08/git-shrinking-subversion-import</id>
  <published>2009-08-08T00:00:00-05:00</published>
  <updated>2009-08-08T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;At &lt;code&gt;$WORK&lt;/code&gt; we’ve been attempting for years—but fairly infrequently—to do distributed development with centralized Subversion. We finally had enough and decided to move to git.&lt;/p&gt;

&lt;p&gt;Part of that move involved importing a couple of projects with 6+ years of history. Early revisions carried lots of binary test data, so &lt;a href=&#39;http://www.kernel.org/pub/software/scm/git/docs/git-svn.html&#39;&gt;git svn&lt;/a&gt; clone produced repositories weighing in at 3.5 and 4.5 gigabytes.&lt;/p&gt;

&lt;p&gt;Another less than satisfactory result was the umpteen bazillion git branches corresponding to git tags. Some of the git branches formed families with names of the form &lt;em&gt;name-x.y.z@1234&lt;/em&gt;, where &lt;em&gt;name-x.y.z&lt;/em&gt; is the name of a Subversion release tag and 1234 was a Subversion revision that modified the tag. A happy design choice made the branch &lt;em&gt;name-x.y.z&lt;/em&gt; (with no &lt;tt&gt;@&lt;i&gt;nnn&lt;/i&gt;&lt;/tt&gt;) the head revision of that Subversion tag, so we easily picked off some targets:&lt;/p&gt;

&lt;p&gt;&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git branch -r -D &lt;span class=&#39;k&#39;&gt;$(&lt;/span&gt;git branch -r | grep @&lt;span class=&#39;k&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Cribbing from &lt;a href=&#39;http://github.com/jcoglan/svn2git/&#39;&gt;svn2git&lt;/a&gt;, converting the git branches to git tags was a series of commands of the form&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git checkout 1.2.3
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git tag -a -m &lt;span class=&#39;s1&#39;&gt;&amp;#39;Tagging release 1.2.3&amp;#39;&lt;/span&gt; v1.2.3
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git branch -r -D 1.2.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then to make the Subversion trunk the git master branch:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git branch -D master
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git checkout trunk
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git checkout -f -b master
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git branch -r -D trunk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s a good point to checkpoint your work in case you hose something later.&lt;/p&gt;

&lt;p&gt;Using &lt;a href=&#39;http://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/&#39;&gt;Antony Stubbs’s script to find the biggest objects in a repo’s packs&lt;/a&gt;, we determined that much of the bulk came from huge &lt;a href=&#39;http://www.hdfgroup.org/HDF5/&#39;&gt;HDF5-format&lt;/a&gt; test baselines along with a few others. So we cut them out:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git filter-branch -d /dev/shm/scratch --index-filter &lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
  &lt;span class=&#39;s2&#39;&gt;&amp;quot;git rm --cached -f --ignore-unmatch &amp;#39;*.h5&amp;#39;; \&lt;/span&gt;
&lt;span class=&#39;s2&#39;&gt;   git rm --cached -f --ignore-unmatch &amp;#39;*.sig&amp;#39;; \&lt;/span&gt;
&lt;span class=&#39;s2&#39;&gt;   git rm --cached -f --ignore-unmatch &amp;#39;*.2dsc&amp;#39;&amp;quot;&lt;/span&gt; &lt;span class=&#39;se&#39;&gt;\&lt;/span&gt;
  --tag-name-filter cat -- --all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The use of &lt;code&gt;--index-filter&lt;/code&gt; makes the long process (remember, it has to hit all possible revisions) quicker because it operates directly on the index rather than checking out every snapshot, munging the filesystem, and shoving the new snapshot back in. Also, &lt;code&gt;/dev/shm&lt;/code&gt; is a &lt;a href=&#39;http://en.wikipedia.org/wiki/TMPFS&#39;&gt;tmpfs&lt;/a&gt; mount for better throughput, and the directory named with &lt;code&gt;-d&lt;/code&gt; shouldn’t exist.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;git filter-branch&lt;/code&gt; manpage has a &lt;a href=&#39;http://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html#_checklist_for_shrinking_a_repository&#39;&gt;checklist for shrinking a repository&lt;/a&gt; that recommends running &lt;code&gt;filter-branch&lt;/code&gt; and then cloning to leave behind the cruft.&lt;/p&gt;

&lt;p&gt;Cloning with a filesystem path makes hardlinks, so use a URL:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git clone file:///home/gbacon/src/repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even after doing this, some big unnamed blobs had survived the clone. Thanks to &lt;a href=&#39;irc://irc.freenote.net/git&#39;&gt;#git on freenode&lt;/a&gt; for the suggestion to excise the &lt;a href=&#39;http://www.gitready.com/intermediate/2009/02/09/reflog-your-safety-net.html&#39;&gt;reflog&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git reflog expire --verbose --expire&lt;span class=&#39;o&#39;&gt;=&lt;/span&gt;0 --all
&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;git gc --prune&lt;span class=&#39;o&#39;&gt;=&lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that these options will require a fairly recent git.&lt;/p&gt;

&lt;p&gt;After all these steps, the git repositories were went from gigabytes to 75 and 100 megabytes, &lt;em&gt;much&lt;/em&gt; nicer!&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/08/git-shrinking-subversion-import.html&quot;&gt;git: shrinking Subversion import&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on August 08, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Simple FitNesse example with CSlim]]></title>
  <link>http://blog.gbacon.com/2009/07/simple-fitnesse-example-with-cslim.html</link>
  <id>http://blog.gbacon.com/2009/07/simple-fitnesse-example-with-cslim</id>
  <published>2009-07-27T00:00:00-05:00</published>
  <updated>2009-07-27T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;Tinkering with the &lt;a href=&#39;http://fitnesse.org/&#39;&gt;FitNesse&lt;/a&gt; acceptance testing system, I cloned the &lt;a href=&#39;http://github.com/dougbradbury/cslim/tree/master&#39;&gt;CSlim repo&lt;/a&gt;, but its &lt;a href=&#39;http://github.com/dougbradbury/cslim/blob/d97a33f6cd881fdf283061f89c2ea9ddd714ac93/README&#39;&gt;README&lt;/a&gt; was short on detail about getting the thing to talk to FitNesse.&lt;/p&gt;

&lt;p&gt;Attempting to build (on Ubuntu karmic) out of the box failed:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;make
compiling ListExecutor.c
compiling SlimConnectionHandler.c
compiling SlimList.c
compiling SlimListDeserializer.c
compiling SlimListSerializer.c
compiling SlimUtil.c
compiling StatementExecutor.c
compiling SymbolTable.c
compiling SocketServer.c
compiling TcpComLink.c
Building archive lib/libCSlim.a
ar: lib/libCSlim.a: No such file or directory
make: *** &lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;lib/libCSlim.a&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; Error 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The workaround is straightforward: &lt;code&gt;mkdir lib&lt;/code&gt; followed by &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So now what?&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;bash&#39;&gt;&lt;span class=&#39;nv&#39;&gt;$ &lt;/span&gt;./CSlim_server --help
getaddrinfo: Servname not supported &lt;span class=&#39;k&#39;&gt;for &lt;/span&gt;ai_socktype
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Following the recommendation in the &lt;a href=&#39;http://fitnesse.org/FitNesse.UserGuide.SliM&#39;&gt;SLiM docs&lt;/a&gt;, I created a page called CslimTest (by editing FrontPage to contain a new line with CslimTest) that contained merely&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After I clicked the Test button, the page cleared, paused for a few seconds, and then gave a red box with “Testing was interupted and results are incomplete.” Clicking Output Captured, I saw a stacktrace that ended with&lt;/p&gt;
&lt;pre&gt;java.lang.ClassNotFoundException: fitnesse.slim.SlimService&lt;/pre&gt;
&lt;p&gt;Maybe I could crib from the docs for another server. The &lt;a href=&#39;http://fitnesse.org/FrontPage.FitNesseDevelopment.DownLoad&#39;&gt;FitNesse download page&lt;/a&gt; points to servers for various languages, and from there I arrived at a &lt;a href=&#39;http://www.syterra.com/Slim/GettingStarted.html&#39;&gt;Getting Started page for fitSharp&lt;/a&gt;, a C# server for FitNesse, which had the following config:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!path c:\myfolder\mytest.dll
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\program files\fitsharp\fitsharp.dll %p}
!define TEST_RUNNER {c:\program files\fitsharp\Runner.exe}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So next I try&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!define TEST_RUNNER {/home/gbacon/src/cslim/CSlim_server}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I got a similar failure, but this time the class that failed to load was &lt;code&gt;.home.gbacon.src.cslim.CSlim_server&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even though the fitSharp used &lt;code&gt;!path&lt;/code&gt; for test assemblies, Drew suggested pointing it to &lt;code&gt;CSlim_server&lt;/code&gt; as in&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!path /home/gbacon/src/cslim/CSlim_server&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But the test still died with &lt;code&gt;ClassNotFoundException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I monkeyed more with &lt;a href=&#39;http://fitnesse.org/FitNesse.UserGuide.CustomizingTestExecution&#39;&gt;&lt;code&gt;COMMAND_PATTERN&lt;/code&gt;&lt;/a&gt;, and finally got a quick error using&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!path /home/gbacon/src/cslim/CSlim_server
!define COMMAND_PATTERN {%m %p}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Instead of Output Captured, I see Tests Executed OK. I notice in &lt;code&gt;src/Main/DecisionTableExample.c&lt;/code&gt; there’s a &lt;code&gt;Division&lt;/code&gt; fixture that seems to match the example in the &lt;a href=&#39;http://fitnesse.org/FitNesse.UserGuide.TwoMinuteExample&#39;&gt;two–minute example&lt;/a&gt;, so I copy-and-paste to get&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!path /home/gbacon/src/cslim/CSlim_server
!define COMMAND_PATTERN {%m %p}

|eg.Division|
|setNumerator|setDenominator|Quotient?|
|10          |2             |5        |
|12.6        |3             |4.2      |
|100         |4             |33       |&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Red box still, and the tests aren’t running. Not much help in the output log, but FitNesse complained:&lt;/p&gt;
&lt;pre&gt;Cannot run program &quot;fitnesse.slim.SlimService&quot;.&lt;/pre&gt;
&lt;p&gt;Remove &lt;code&gt;%m&lt;/code&gt; from &lt;code&gt;COMMAND_PATTERN&lt;/code&gt;. Progress! Nothing’s running, but I see a bunch of exceptions and text with yellow backgrounds, such as “eg.Division Could not find class eg.Division.” Maybe it doesn’t like the leading &lt;code&gt;eg&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!path /home/gbacon/src/cslim/CSlim_server
!define COMMAND_PATTERN {%p}

|Division|
|setNumerator|setDenominator|Quotient?|
|10          |2             |5        |
|12.6        |3             |4.2      |
|100         |4             |33       |&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now Division goes green, but it doesn’t like the input methods (&lt;tt&gt;&quot;Method setSetNumerator\[1] not found in Division.&quot;&lt;/tt&gt; for example). The method names in the fixture are &lt;code&gt;setNumerator&lt;/code&gt;, &lt;code&gt;setDenominator&lt;/code&gt;, and &lt;code&gt;Quotient&lt;/code&gt;, so mangling must be happening somewhere.&lt;/p&gt;

&lt;p&gt;That’s what I get for trying to think ahead of it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;!define TEST_SYSTEM {slim}
!define COMMAND_PATTERN {%p}
!path /home/gbacon/src/cslim/CSlim_server

|Division|
|numerator|denominator|Quotient?|
|10       |2          |5        |
|12.6     |3          |4.2      |
|100      |4          |33       |&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now the first two rows pass, and the third fails as expected.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/07/simple-fitnesse-example-with-cslim.html&quot;&gt;Simple FitNesse example with CSlim&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on July 27, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Just for you, Madeline]]></title>
  <link>http://blog.gbacon.com/2009/07/just-for-you-madeline.html</link>
  <id>http://blog.gbacon.com/2009/07/just-for-you-madeline</id>
  <published>2009-07-11T00:00:00-05:00</published>
  <updated>2009-07-11T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;object height=&quot;250&quot; width=&quot;400&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://gbacon.github.io/words.swf&quot; /&gt;&lt;embed height=&quot;250&quot; src=&quot;http://gbacon.github.io/words.swf&quot; width=&quot;400&quot; /&gt;&lt;/object&gt;
&lt;p&gt; My five-year-old daughter is learning to read. I made flash cards for us to practice phonics and recognition, and I wrote this simple app to give her a way to practice on her own too. Thanks to the &lt;a href=&quot;http://en.wiktionary.org/&quot;&gt;Wiktionary&lt;/a&gt; folks for the pronunciations. 
&lt;p&gt; Along with the buttons, you can advance by pressing Enter or Right-Arrow and hear the word with S or space bar.
&lt;p&gt; The &lt;a href=&quot;http://github.com/gbacon/learn-words/&quot;&gt;code is available on GitHub&lt;/a&gt;.

  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/07/just-for-you-madeline.html&quot;&gt;Just for you, Madeline&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on July 11, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Cleaning up your Haskell imports]]></title>
  <link>http://blog.gbacon.com/2009/06/cleaning-up-your-haskell-imports.html</link>
  <id>http://blog.gbacon.com/2009/06/cleaning-up-your-haskell-imports</id>
  <published>2009-06-29T00:00:00-05:00</published>
  <updated>2009-06-29T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;Explicit imports have a couple of benefits. For one, doing so &lt;a href=&#39;http://www.haskell.org/ghc/docs/6.0/html/users_guide/sooner-faster-quicker.html&#39;&gt;reduces compile times with ghc&lt;/a&gt;. Another is giving a hand to your future self (or other maintainers) and especially to those who are reading your code to learn. We’ve all been there: scratching our heads wondering, ‘Where does &lt;em&gt;that&lt;/em&gt; function live?’ Yes, &lt;a href=&#39;http://www.haskell.org/ghc/docs/6.10.3/html/users_guide/ghci-commands.html#id2899386&#39;&gt;ghci’s &lt;code&gt;:info&lt;/code&gt; command&lt;/a&gt; and &lt;a href=&#39;http://www.haskell.org/hoogle/&#39;&gt;Hoogle&lt;/a&gt; are your friends, but explicit imports right there in your code will give the answer in a snap.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#39;http://neilmitchell.blogspot.com/2009/01/small-scripts-with-haskell.html&#39;&gt;Neil Mitchell calls explicit imports “needlessly verbose,”&lt;/a&gt; certainly a fair point in the context where he made it, so this is a matter of polish, not strict necessity. There’s also a certain aspy-appeal to it.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&#39;http://www.haskell.org/ghc/docs/6.10.3/html/users_guide/separate-compilation.html#id2915722&#39;&gt;&lt;code&gt;-ddump-minimal-imports&lt;/code&gt; option to ghc&lt;/a&gt; writes the cleaned–up list to &lt;code&gt;M.imports&lt;/code&gt;, where &lt;i&gt;M&lt;/i&gt; is the module being compiled. For example, consider the following code that finds anagrams in a dictionary file:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;kr&#39;&gt;module&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Main&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;

&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Control.Arrow&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Control.Monad&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.Char&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.List&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.Map&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;hiding&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;filter&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;map&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;System.Environment&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;System.Exit&lt;/span&gt;
&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;System.IO&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;usage&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;IO&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;usage&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;me&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getProgName&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;hPutStrLn&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;stderr&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;Usage: &amp;quot;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;me&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot; [ dictionary ]&amp;quot;&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;exitWith&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;ExitFailure&lt;/span&gt; &lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;main&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;IO&lt;/span&gt; &lt;span class=&#39;nb&#39;&gt;()&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;main&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;getPath&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;readFile&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;mapM_&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;putStrLn&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;unwords&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sorted&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sorted&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;anagrams&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;lines&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;anagrams&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]]&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;anagrams&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;words&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;filter&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#39;mi&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;length&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;equiv&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;equiv&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;elems&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;
                  &lt;span class=&#39;n&#39;&gt;fromListWith&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;++&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
                    &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;normal&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;w&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;])&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;words&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;normal&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sort&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;.&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;toLower&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;getPath&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;IO&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;FilePath&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;getPath&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;getArgs&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;/usr/share/dict/words&amp;quot;&lt;/span&gt;
        &lt;span class=&#39;n&#39;&gt;go&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;_&lt;/span&gt;      &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;usage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To get the minimal set of imports:&lt;/p&gt;
&lt;pre&gt;$ ghc-6.10.3 -ddump-minimal-imports --make anagram.hs
$ cat Main.imports
import System.IO(IO, FilePath, putStrLn, readFile, hPutStrLn,
                 stderr)
import Data.Map(elems, fromListWith)
import Control.Arrow()    -- Instances only
import Control.Monad(Monad(return, (&gt;&gt;=)), mapM_)
import Data.Char(String, toLower)
import Data.List((++), filter, map, length, lines, unwords, sort)
import System.Environment(getArgs, getProgName)
import System.Exit(ExitCode(ExitFailure), exitWith)&lt;/pre&gt;
&lt;p&gt;Although nice, the result is less than satisfying. The cuddled lists are ugly. The imports are in an odd order. Having to do run a separate compilation by hand followed by copy-paste, as opposed to automatically à la &lt;a href=&#39;http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.jdt.doc.user/reference/ref-22.htm&#39;&gt;Eclipse’s organize imports for Java&lt;/a&gt;, is a bit of a pain.&lt;/p&gt;

&lt;p&gt;Notice that although Control.Arrow is unnecessary, it remains in the “minimal” set with an empty import list. Its presence is an artifact of the list comprehension being equivalent to&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;normal&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:[]&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;words&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool, yes. Readable, not so much.&lt;/p&gt;

&lt;p&gt;Note also there’s an &lt;a href=&#39;http://hackage.haskell.org/trac/ghc/ticket/1792&#39;&gt;open ticket against ghc concerning the interaction between &lt;code&gt;-ddump-minimal-imports&lt;/code&gt; and qualified imports&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2009/06/cleaning-up-your-haskell-imports.html&quot;&gt;Cleaning up your Haskell imports&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on June 29, 2009.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[My first monadic program!]]></title>
  <link>http://blog.gbacon.com/2007/02/my-first-monadic-program.html</link>
  <id>http://blog.gbacon.com/2007/02/my-first-monadic-program</id>
  <published>2007-02-25T00:00:00-06:00</published>
  <updated>2007-02-25T00:00:00-06:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;&lt;a href=&#39;http://projecteuler.net/index.php?section=problems&amp;amp;id=32&#39;&gt;Problem 32&lt;/a&gt; from &lt;a href=&#39;http://projecteuler.net/&#39;&gt;Project Euler&lt;/a&gt; reads&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital.&lt;/p&gt;

&lt;p&gt;Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not one of my brighter moments, the first approach I considered was applying &lt;em&gt;goon&lt;/em&gt;–force to permute a list of eleven characters (&lt;code&gt;&amp;#39;1&amp;#39; .. &amp;#39;9&amp;#39;&lt;/code&gt;, &lt;code&gt;&amp;#39;x&amp;#39;&lt;/code&gt;, and &lt;code&gt;&amp;#39;=&amp;#39;&lt;/code&gt;) — a search space of almost 40 million — looking for well-formed and valid statements.&lt;/p&gt;

&lt;p&gt;Initially, I looked at using &lt;a href=&#39;http://haskell.org/ghc/docs/latest/html/libraries/regex-compat/Text-Regex.html&#39;&gt;Text.Regex&lt;/a&gt;. As I was fishing for examples to crib from, I saw a suggestion that people may as well use &lt;a href=&#39;http://www.cs.uu.nl/~daan/parsec.html&#39;&gt;Parsec&lt;/a&gt;, the monadic parser combinator library. So let’s knock out the preliminaries:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;module&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Main&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Data.List&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;hiding&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;map&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;import&lt;/span&gt; &lt;span class=&#39;nn&#39;&gt;Text.ParserCombinators.Parsec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A parser for the simple expressions reads easily:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;num&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Parser&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;num&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ns&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;many1&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;digit&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;          &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;read&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ns&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;expression&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Parser&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;expression&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;multiplier&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;num&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;times&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;char&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;multiplicand&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;num&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;equals&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;char&lt;/span&gt; &lt;span class=&#39;sc&#39;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;product&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;num&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;                 &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;multiplier&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;multiplicand&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;product&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Generating permutations is no problem in Haskell:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;y&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zs&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;y&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;ys&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;selections&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;zs&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;ys&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;selections&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt;     &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;[]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;selections&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;y&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;ys&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;y&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;ys&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;selections&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;xs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I’d been wanting to solve as a learning example one of the Project&amp;#160;Euler problems using monads. As I tried to shoehorn the problem into a monadic solution, I remembered the characterization of the &lt;code&gt;Maybe&lt;/code&gt; monad as being useful for computations that can fail, and I saw two possibilities for failure: garbage input (&lt;em&gt;e.g.&lt;/em&gt;, &lt;code&gt;&amp;quot;x=123456789&amp;quot;&lt;/code&gt;) and false statements (&lt;em&gt;e.g.&lt;/em&gt;, &lt;code&gt;&amp;quot;1x2=3456789&amp;quot;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Having a particular permutation, &lt;code&gt;check&lt;/code&gt; tests whether it’s well–formed and valid:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Maybe&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;result&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;validProduct&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;result&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Maybe&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;case&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;parse&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;expression&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;of&lt;/span&gt;
    &lt;span class=&#39;kt&#39;&gt;Left&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;err&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Nothing&lt;/span&gt;
    &lt;span class=&#39;kt&#39;&gt;Right&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tuple&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;@&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;md&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tuple&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;validProduct&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;md&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;*&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;md&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Just&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;
  &lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;otherwise&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Nothing&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The test goes just as you would describe it to someone else: parse the input to extract the multiplier, multiplicand, and product. Then check whether the operation holds. Simple.&lt;/p&gt;

&lt;p&gt;Fitting these puzzle pieces together also helped another concept click. I remember reading characterizations of being “inside the monad” and feeling mystified. Notice, for example, that &lt;code&gt;parseExpr&lt;/code&gt; has type &lt;code&gt;String&lt;/code&gt;&amp;#160;→&amp;#160;&lt;code&gt;Maybe (Int,Int,Int)&lt;/code&gt;. That is, given a string, the result is either &lt;code&gt;Nothing&lt;/code&gt; or &lt;code&gt;Just x&lt;/code&gt;, where &lt;em&gt;x&lt;/em&gt; is a 3-tuple. Another way to think about the latter case is &lt;code&gt;Just&lt;/code&gt; with some &lt;code&gt;(Int,Int,Int)&lt;/code&gt; &lt;em&gt;inside&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Continuing the concept, consider how &lt;code&gt;parseExpr&lt;/code&gt; is used in &lt;code&gt;check&lt;/code&gt;. The result from &lt;code&gt;parseExpr&lt;/code&gt; becomes on the next line an argument to &lt;code&gt;validProduct&lt;/code&gt;. You might be tempted to object that the types don’t line up! &lt;code&gt;validProduct&lt;/code&gt; wants a plain tuple, but &lt;code&gt;parseExpr&lt;/code&gt; gives &lt;code&gt;Maybe (Int,Int,Int)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the program to typecheck, &lt;code&gt;result&lt;/code&gt; must be a tuple with no wrapper. When “inside the monad,” you can directly access the value without having to explicitly unwrap it.&lt;/p&gt;

&lt;p&gt;You wonder, &lt;em&gt;‘But what about when the parse fails or when the statement is bogus?’&lt;/em&gt; In addition to implicitly unwrapping, the &lt;code&gt;Maybe&lt;/code&gt; monad and do-notation syntactic sugar are checking these cases too! “Control” (to borrow an imperative concept) reaches the &lt;code&gt;return p&lt;/code&gt; line only if both &lt;code&gt;parseExpr&lt;/code&gt; and &lt;code&gt;validProduct&lt;/code&gt; succeed. Otherwise, &lt;code&gt;check&lt;/code&gt; bails where the failure occurs and returns &lt;code&gt;Nothing&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All that’s left to do is feed it input and sum the result. Note: it’s very s-l-o-w.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;haskell&#39;&gt;&lt;span class=&#39;nf&#39;&gt;p32&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sum&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;elems&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fromList&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;catMaybes&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;map&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;cs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;cs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;4&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;6&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;7&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;8&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An obvious improvement is to use &lt;a href=&#39;http://haskell.org/ghc/docs/latest/html/libraries/base/Data-List.html#v%3Anub&#39;&gt;&lt;code&gt;nub&lt;/code&gt;&lt;/a&gt; instead of &lt;code&gt;(elems . fromList)&lt;/code&gt;. Even better, lists are also monads, so &lt;code&gt;Maybe&lt;/code&gt; distractions disappear with only a few very minor changes:&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;literate-haskell&#39;&gt;&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;p32&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;sum&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;nub&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;$&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;concatMap&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;permutations&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;cs&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;where&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;cs&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;4&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;5&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;6&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;7&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;8&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;&amp;#39;x&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;sc&#39;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;]&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;main&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;print&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p32&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Monad&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;check&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;do&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;result&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;p&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;validProduct&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;result&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;p&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Monad&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;String&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;parseExpr&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;     &lt;/span&gt;&lt;span class=&#39;kr&#39;&gt;case&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;parse&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;expression&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;expression&amp;quot;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;s&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;of&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Left&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;err&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fail&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;show&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;err&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;       &lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Right&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tuple&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;@&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;md&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;tuple&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;validProduct&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;::&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Monad&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;m&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;Int&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;validProduct&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;md&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;mr&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;*&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;md&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;return&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;pr&lt;/span&gt;
&lt;span class=&#39;cs&#39;&gt;&amp;gt;   &lt;/span&gt;&lt;span class=&#39;o&#39;&gt;|&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;otherwise&lt;/span&gt; &lt;span class=&#39;ow&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;fail&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;invalid product&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This works because failure in the list monad is the empty list, and &lt;code&gt;concatMap&lt;/code&gt; gets rid of all the empties.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2007/02/my-first-monadic-program.html&quot;&gt;My first monadic program!&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on February 25, 2007.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Trigonometry refactored?]]></title>
  <link>http://blog.gbacon.com/2005/09/trigonometry-refactored.html</link>
  <id>http://blog.gbacon.com/2005/09/trigonometry-refactored</id>
  <published>2005-09-17T00:00:00-05:00</published>
  <updated>2005-09-17T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;This afternoon on &lt;a href=&quot;irc://irc.pobox.com/perl&quot;&gt;#perl&lt;/a&gt;, the topic was &amp;quot;Trig &lt;a href=&quot;http://xp.c2.com/RefactorMercilessly.html&quot;&gt;refactored&lt;/a&gt; to remove sin/cos/tan&amp;quot; with a pointer to the upcoming &lt;a href=&quot;http://web.maths.unsw.edu.au/~norman/book.htm&quot;&gt;&lt;cite&gt;Divine Proportions: Rational Trigonometry to Universal Geometry&lt;/cite&gt;&lt;/a&gt; by N J Wildberger.
&lt;p&gt;The &lt;a href=&quot;http://web.maths.unsw.edu.au/~norman/papers/Introduction.pdf&quot;&gt;introduction&lt;/a&gt; makes an ambitious claim:
&lt;blockquote&gt;&lt;p&gt;Rational trigonometry deals with many practical problems in an easier and more elegant fashion than classical trigonometry, and often ends up with answers that are demonstrably more accurate. In fact rational trigonometry is so elementary that almost all calculations may be done by hand. Tables or calculators are not necessary, although the latter certainly speed up computations. It is a shame that this theory was not discovered earlier, since accurate tables were for many centuries not widely available.&lt;p&gt;Because rational trigonometry uses only arithmetic and algebra, it allows the development of Euclidean geometry in a consistent and general way in an arbitrary field. This is &lt;i&gt;universal geometry&lt;/i&gt;.&lt;/blockquote&gt;
&lt;p&gt;Emphasis Wildberger&amp;#39;s, not mine. I look forward to reading more!
&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img alt=&quot;&quot; class=&quot;posterous_download_image&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/16846333-112699625914743988?l=gbacon.blogspot.com&quot; width=&quot;1&quot; /&gt;&lt;/div&gt;

  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2005/09/trigonometry-refactored.html&quot;&gt;Trigonometry refactored?&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on September 17, 2005.&lt;/p&gt;</content>
</entry>


<entry>
  <title type="html"><![CDATA[Processing lines in a TextBox]]></title>
  <link>http://blog.gbacon.com/2005/07/processing-lines-in-textbox.html</link>
  <id>http://blog.gbacon.com/2005/07/processing-lines-in-textbox</id>
  <published>2005-07-05T00:00:00-05:00</published>
  <updated>2005-07-05T00:00:00-05:00</updated>
  <author>
    <name>Greg Bacon</name>
    <uri>http://blog.gbacon.com</uri>
    <email>gbacon@gbacon.com</email>
  </author>
  <content type="html">&lt;p&gt;Below is a simple example of processing all lines in a TextBox.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre&gt;&lt;code class=&#39;csharp&#39;&gt;&lt;span class=&#39;k&#39;&gt;public&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;static&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;void&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;WriteFile&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;contents&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
  &lt;span class=&#39;k&#39;&gt;using&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;StreamWriter&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;new&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;StreamWriter&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt;
    &lt;span class=&#39;n&#39;&gt;w&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;Write&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;contents&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;public&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;static&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;void&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;LineByLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;TextReader&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reader&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;Console&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;WriteLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&amp;quot;input type = &amp;quot;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reader&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;GetType&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;());&lt;/span&gt;

  &lt;span class=&#39;kt&#39;&gt;int&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;n&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
  &lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
  &lt;span class=&#39;k&#39;&gt;while&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;((&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;line&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;reader&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;ReadLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;())&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;!=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;null&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
    &lt;span class=&#39;n&#39;&gt;Console&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;WriteLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;n&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;++&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;. [&amp;quot;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;line&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;]&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;

&lt;span class=&#39;k&#39;&gt;static&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;void&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;Main&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;[]&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;args&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;{&lt;/span&gt;
  &lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt;
    &lt;span class=&#39;s&#39;&gt;&amp;quot;The quick\n&amp;quot;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt;
    &lt;span class=&#39;s&#39;&gt;&amp;quot;brown fox jumped over\n&amp;quot;&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;+&lt;/span&gt;
    &lt;span class=&#39;s&#39;&gt;&amp;quot;the lazy dog.&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;

  &lt;span class=&#39;kt&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;WriteFile&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;,&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;text&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
  &lt;span class=&#39;k&#39;&gt;using&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;StreamReader&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;streamr&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;new&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;StreamReader&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt;
    &lt;span class=&#39;n&#39;&gt;LineByLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;streamr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;

  &lt;span class=&#39;n&#39;&gt;TextBox&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;textbox&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;new&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;TextBox&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;();&lt;/span&gt;
  &lt;span class=&#39;n&#39;&gt;textbox&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;Text&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;text&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;;&lt;/span&gt;
  &lt;span class=&#39;k&#39;&gt;using&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;StringReader&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;stringr&lt;/span&gt; &lt;span class=&#39;p&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;k&#39;&gt;new&lt;/span&gt; &lt;span class=&#39;n&#39;&gt;StringReader&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;textbox&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;.&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;Text&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;))&lt;/span&gt;
    &lt;span class=&#39;n&#39;&gt;LineByLine&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;n&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;p&#39;&gt;);&lt;/span&gt;
&lt;span class=&#39;p&#39;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;p&gt;&lt;a href=&quot;http://blog.gbacon.com/2005/07/processing-lines-in-textbox.html&quot;&gt;Processing lines in a TextBox&lt;/a&gt; was originally published by Greg Bacon at &lt;a href=&quot;http://blog.gbacon.com&quot;&gt;blog.gbacon.com&lt;/a&gt; on July 05, 2005.&lt;/p&gt;</content>
</entry>

</feed>
