<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>engel</title>
    <link>http://engel.uk.to</link>
    <atom:link href="http://engel.uk.to/rss.xml" rel="self" type="application/rss+xml" />
    <language>en-US</language>
    <pubDate>Wed, 17 Apr 2013 20:06:42 -0700</pubDate>
    <lastBuildDate>Wed, 17 Apr 2013 20:06:42 -0700</lastBuildDate>

    
    <item>
      <title>Review&#58; Clojure Programming by Chas Emerick et al.</title>
      <link>http://engel.uk.to/2013/programming-clojure/</link>
      <pubDate>Wed, 17 Apr 2013 00:00:00 -0700</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2013/programming-clojure/</guid>
      <description>&lt;p&gt;I often run into what you might call &lt;em&gt;closet functional programmers&lt;/em&gt; &amp;ndash; people
who seem to have a genuine interest in acquainting themselves with a new
paradigm, but just can&amp;rsquo;t manage to find the time to do it. Some of those who do
invest the time often end up on something like the &lt;a href=&quot;http://www.haskell.org/haskellwiki/Typeclassopedia&quot;&gt;Typeclassopedia&lt;/a&gt;&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;,
where the combined force of jargon and type signatures kill whatever interest
they began with.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;http://www.amazon.com/gp/product/1449394701/ref=as_li_tf_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=1449394701&amp;amp;linkCode=as2&amp;amp;tag=blog0cbb-20&quot;&gt;&lt;em&gt;Clojure Programming&lt;/em&gt;&lt;/a&gt;, though, I&amp;rsquo;m happy to report that this will
no longer be a problem. This book gives hope to those who have championed Lisp
and / or functional programming in vain. Emerick et al. provide not only a
thorough tour of the language, but also demonstrate the beauty and conciseness
of its solutions to common problems. The book dedicates an entire section
(&amp;ldquo;Practicum&amp;rdquo;) to describing how Clojure is idiomatically used in different
application domains.&lt;/p&gt;

&lt;p&gt;I was particularly pleased by the stellar coverage of some of Clojure&amp;rsquo;s most
compelling features:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Concurrency primitives (&lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;atom&lt;/code&gt;, &lt;code&gt;agent&lt;/code&gt;, &lt;code&gt;future&lt;/code&gt;, and friends)&lt;/li&gt;
  &lt;li&gt;The power of the JVM and easy Java interop&lt;/li&gt;
  &lt;li&gt;Lisp syntax (which makes for easy and &lt;em&gt;powerful&lt;/em&gt; metaprogramming)&lt;/li&gt;
  &lt;li&gt;The sequence abstraction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These features are all explained in a bottom-up style (fitting for a Lisp!) &amp;ndash;
the authors build up a sizeable example by providing an implementation in small
increments, explaining along the way. This style is a nice parallel to the
nature of traditional Lisp programming.&lt;/p&gt;

&lt;p&gt;This book would fit best any of these three groups:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Java refugees.&lt;/strong&gt; Give me the JVM, hold the
  &lt;a href=&quot;http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.html&quot;&gt;&lt;code&gt;AbstractSingletonProxyFactoryBean&lt;/code&gt;&lt;/a&gt;. &lt;em&gt;Clojure Programming&lt;/em&gt; shows you
  how to take advantage of the vast Java ecosystem while avoiding some of the
  pitfalls of having static typing and OOP forced upon you. The authors make a
  good case for interactive programming with the Clojure REPL, which gives you
  a direct line to the JVM not usually available in Java-land.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Beginning functional programmers.&lt;/strong&gt; For those already acquainted with a
  scripting language like Python, Ruby, etc., your first Clojure programs will
  be a breeze. The book spends a chapter first easing you into Clojure syntax
  before presenting the basics of functional programming in all of their
  greatness. You&amp;rsquo;ll come to love the paradigm and appreciate how Clojure
  facilitates its use so effectively.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Lispers.&lt;/strong&gt; While Clojure is by no means a mainstream language, it provides a
  compelling case of a successful Lisp dialect. The later chapters, which
  provide examples of Clojure applications in all sorts of distinct domains,
  will definitely be of interest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beginners, intermediate users and masters alike will find something of use in
&lt;em&gt;Clojure Programming&lt;/em&gt;. It&amp;rsquo;ll be one of the first books I recommend from now on
to anyone curious about Lisp or functional programming.&lt;/p&gt;

&lt;p&gt;(Disclosure: I received an electronic copy of this book in exchange for writing
a review.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=blog0cbb-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=1449394701&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;I&amp;rsquo;ve absolutely nothing against this document &amp;ndash; it&amp;rsquo;s a fascinating and wonderfully helpful piece of work &amp;ndash; but when the first few paragraphs include the words &amp;ldquo;category theory,&amp;rdquo; &amp;ldquo;monoid,&amp;rdquo; etc., etc., beginners will tend to get spooked!&lt;a href=&quot;#fnref:1&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Parsing sound change rules with Parsec&#58; Part 2</title>
      <link>http://engel.uk.to/2012/sound-change-parsing-parsec-rules/</link>
      <pubDate>Mon, 17 Dec 2012 00:00:00 -0800</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/sound-change-parsing-parsec-rules/</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the second post in a tutorial series on applying Parsec in
 historical linguistics. We&amp;rsquo;ve begun by providing a more formal
 description of sound change rule grammars and will end by building a
 full-fledged sound change applier.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href=&quot;/2012/sound-change-parsing-bnf-grammar&quot;&gt;last post&lt;/a&gt; we established a BNF grammar for files which
describe sound change rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;file&amp;gt;               ::= (&amp;lt;phoneme-class-defn&amp;gt; &amp;lt;EOL&amp;gt;)* (&amp;lt;rule&amp;gt; &amp;lt;EOL&amp;gt;)+
&amp;lt;phoneme-class-defn&amp;gt; ::= &amp;lt;phoneme-class&amp;gt; &quot;:&quot; &amp;lt;phoneme&amp;gt;+
&amp;lt;rule&amp;gt;               ::= &amp;lt;context&amp;gt; &quot;&amp;gt;&quot; &amp;lt;replacement&amp;gt; [&quot;/&quot; &amp;lt;condition&amp;gt;]
&amp;lt;condition&amp;gt;          ::= &amp;lt;context&amp;gt;_&amp;lt;context&amp;gt;
&amp;lt;context&amp;gt;            ::= (&amp;lt;phoneme&amp;gt; | &amp;lt;phoneme-class&amp;gt;)+
&amp;lt;phoneme&amp;gt;            ::= &amp;lt;lowercase-letter&amp;gt;
&amp;lt;phoneme-class&amp;gt;      ::= &amp;lt;uppercase-letter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Before we begin parsing, let&amp;rsquo;s set up some basic datatypes which can be
used to store the parse results.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data.Map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- A single phoneme.&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- Phoneme class storage, mapping from a single character (&amp;#39;V&amp;#39;, &amp;#39;A&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- &amp;#39;F&amp;#39;, etc.) to a collection of phonemes.&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- A string of phonemes used to match a given context.&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- A complete sound change rule.&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;replacement&lt;/span&gt;   &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                   &lt;span class=&quot;n&quot;&gt;beforeContext&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;n&quot;&gt;inContext&lt;/span&gt;     &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                   &lt;span class=&quot;n&quot;&gt;afterContext&lt;/span&gt;  &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Rule&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot; &amp;gt; &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot; / &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
                          &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;_&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;show&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Referencing the BNF grammar, we can use these types to build the returns
for our parsers. Let&amp;rsquo;s start with the simplest Parsec rules,
&lt;code&gt;anyPhoneme&lt;/code&gt; and &lt;code&gt;anyPhonemeClass&lt;/code&gt;. Any uppercase character in sound
change rules should be interpreted as a phoneme class reference, and any
lowercase character must be a phoneme.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Text.Parsec&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;anyPhoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Parsec&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;anyPhoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Parsec&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upper&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As evidenced by the given type annotations, our parsers (for the moment)
will have a stream type of &lt;code&gt;String&lt;/code&gt;, a user state type of &lt;code&gt;()&lt;/code&gt;, and a
return type that varies based on their purpose.&lt;/p&gt;

&lt;h2 id=&quot;our-first-lift&quot;&gt;Our first lift&lt;/h2&gt;

&lt;p&gt;We need to next build the parser for phoneme class definitions. As a
first try, we could have our parser return a pair of type &lt;code&gt;(Char,
[Phoneme])&lt;/code&gt;, matching with the type of a &lt;code&gt;PhonemeClassMap&lt;/code&gt;. Let&amp;rsquo;s start:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Parsec&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This doesn&amp;rsquo;t work! What gives?&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at the type of &lt;code&gt;(,)&lt;/code&gt;, a tuple constructor:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And check the type of &lt;code&gt;anyPhonemeClass&lt;/code&gt; and &lt;code&gt;many1 anyPhoneme&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;anyPhonemeClass&lt;/span&gt;  &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;These have the right types &lt;code&gt;Char&lt;/code&gt; and &lt;code&gt;[Phoneme]&lt;/code&gt;, except they&amp;rsquo;re
contained within a &lt;code&gt;ParsecT&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;Good news: &lt;code&gt;ParsecT s u m&lt;/code&gt; is a functor! This means that we can &amp;ldquo;lift&amp;rdquo;
functions into the context defined by the type. Check the type of &lt;code&gt;fmap&lt;/code&gt;
and &lt;code&gt;fmap (,)&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;fmap&lt;/span&gt;     &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can check that the type of &lt;code&gt;(,)&lt;/code&gt; corresponds with the type of &lt;code&gt;fmap
(,)&lt;/code&gt;. (In &lt;code&gt;fmap&lt;/code&gt;&amp;rsquo;s type signature, &lt;code&gt;b&lt;/code&gt; corresponds to &lt;code&gt;b -&amp;gt; (a, b)&lt;/code&gt; from
&lt;code&gt;(,)&lt;/code&gt;&amp;rsquo;s type.)&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s provide &lt;code&gt;fmap (,)&lt;/code&gt; with that first argument &lt;code&gt;f a&lt;/code&gt;, where &lt;code&gt;f&lt;/code&gt; is
&lt;code&gt;ParsecT String () Identity&lt;/code&gt; and &lt;code&gt;a&lt;/code&gt; is &lt;code&gt;Char&lt;/code&gt;. (This looks like the
type of &lt;code&gt;anyPhonemeClass&lt;/code&gt;!)&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;fmap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Great - just as &lt;code&gt;fmap&lt;/code&gt;&amp;rsquo;s signature described, &lt;code&gt;(,)&lt;/code&gt; was lifted into the
&lt;code&gt;ParsecT String () Identity&lt;/code&gt; context and &lt;code&gt;a&lt;/code&gt; was clarified to be a
&lt;code&gt;Char&lt;/code&gt;. We can make our expression look a bit nicer by using an infix
alias for &lt;code&gt;fmap&lt;/code&gt; from &lt;code&gt;Control.Applicative&lt;/code&gt;, &lt;code&gt;&amp;lt;$&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;applying-within-a-context&quot;&gt;Applying within a context&lt;/h2&gt;

&lt;p&gt;Looking at the types, we&amp;rsquo;re almost there: we want our final parser to
have a return type of &lt;code&gt;(Char, [Phoneme])&lt;/code&gt; and the current parser has a
return type of &lt;code&gt;b -&amp;gt; (Char, b)&lt;/code&gt;. How can we supply a type &lt;code&gt;b&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The answer comes from the fact that &lt;code&gt;ParsecT s u m&lt;/code&gt; is not only a
functor but an &lt;em&gt;applicative&lt;/em&gt; functor. This means that we can apply
functions already within the context (like &lt;code&gt;b -&amp;gt; (Char, b)&lt;/code&gt;!) to values
within the context (like &lt;code&gt;anyPhoneme&lt;/code&gt;!).&lt;/p&gt;

&lt;p&gt;This contextual application is invoked by &lt;code&gt;Control.Applicative&lt;/code&gt;&amp;rsquo;s &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;.
Compare its type with the type of &lt;code&gt;$&lt;/code&gt;: the only difference is that &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;
operates within a context &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt;                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s apply the lifted and partially applied function from the last
section to &lt;code&gt;anyPhoneme&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;anyPhoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Close: our return type is &lt;code&gt;(Char, Phoneme)&lt;/code&gt;. Let&amp;rsquo;s apply with a &lt;code&gt;many1
anyPhoneme&lt;/code&gt; instead, which will produce a parser that accepts one or
more phonemes.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Great! Our parser returns the proper type. Let&amp;rsquo;s write the actual
implementation of our phoneme class definition rule before continuing:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Control.Applicative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We must do a bit of bookkeeping. In the original BNF, we stated that a
phoneme class definition was of the form&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;phoneme-class-defn&amp;gt; ::= &amp;lt;phoneme-class&amp;gt; &quot;:&quot; &amp;lt;phoneme&amp;gt;+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need to account for the &amp;ldquo;useless&amp;rdquo; colon in this expression. It&amp;rsquo;s
useless in that it contributes nothing to the parse result. Using the
&lt;code&gt;*&amp;gt;&lt;/code&gt; function from &lt;code&gt;Control.Applicative&lt;/code&gt;, we can consume a &lt;code&gt;':'&lt;/code&gt;
character and discard its result:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Control.Applicative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(,)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt;
                          &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;modifying-user-state&quot;&gt;Modifying user state&lt;/h2&gt;

&lt;p&gt;There&amp;rsquo;s one significant problem left with this parser. True, it eats up
strings without a problem:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;V:aeiou&amp;quot;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;&amp;#39;V&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;aeiou&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Our problem is that we need to reference these definitions in another
parser, specifically the &lt;em&gt;context parser&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;context&amp;gt; ::= (&amp;lt;phoneme&amp;gt; | &amp;lt;phoneme-class&amp;gt;)+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Since Parsec has no idea of what a phoneme class is, when we build this
parser we&amp;rsquo;ll need to identify exactly what we should look for in test
words given that we saw &amp;ldquo;V&amp;rdquo; or &amp;ldquo;A&amp;rdquo; in a rule. How can we have the
phoneme class definitions &amp;ldquo;carry over?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s simple using Parsec&amp;rsquo;s built-in &amp;ldquo;user state&amp;rdquo; feature. (It shows up
in the &lt;code&gt;u&lt;/code&gt; in &lt;code&gt;ParsecT s u m a&lt;/code&gt;.) Rather than using &lt;code&gt;()&lt;/code&gt; as our user
state type, let&amp;rsquo;s carry along a &lt;code&gt;PhonemeClassMap&lt;/code&gt; as state. Each rule&amp;rsquo;s
type needs to now be redefined (but the implementation for those not
using the state data need not change):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;anyPhoneme&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;phonemeClassDefinition&lt;/code&gt; we&amp;rsquo;ll need to use Parsec&amp;rsquo;s &lt;code&gt;modifyState&lt;/code&gt;
function:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;modifyState&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This type annotation does a great job of helping us understand what
exactly happens within the function. Given some user state modifier
(i.e., a function which takes an old user state of type &lt;code&gt;u&lt;/code&gt; and creates
a new one), a new parser is yielded which has a user state of type &lt;code&gt;u&lt;/code&gt;
and returns nothing.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;phonemeClassDefinition&lt;/code&gt; will return nothing and instead modify the
parser&amp;rsquo;s state (i.e., add entries to the phoneme class map).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We want to modify this map by &lt;code&gt;insert&lt;/code&gt;ing an entry whose contents will
be equal . We run into a familiar problem, however, since &lt;code&gt;insert&lt;/code&gt; was
not built explicitly for use with the &lt;code&gt;ParsecT s u m&lt;/code&gt; context:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s lift &lt;code&gt;insert&lt;/code&gt; into the &lt;code&gt;ParsecT s u m&lt;/code&gt; functor:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Functor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;
                                                   &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
                                                  &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Close, like before: we can now provide &lt;code&gt;fmap insert&lt;/code&gt; with a first
argument in the &lt;code&gt;ParsecT s u m&lt;/code&gt; context, but the &lt;code&gt;a1&lt;/code&gt; in the type
annotation has no concept of context. Using &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt; once more, we can fix
the problem:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Before continuing, let&amp;rsquo;s give a name to the parser created in this
section.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Phoneme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice that &lt;code&gt;Map Char [Phoneme]&lt;/code&gt; is equivalent to &lt;code&gt;PhonemeClassMap&lt;/code&gt;, or
our parser&amp;rsquo;s user state &lt;code&gt;u&lt;/code&gt;. We just did all this work to lift and apply
&lt;code&gt;insert&lt;/code&gt; within a context, but now, upon revisiting &lt;code&gt;modifyState&lt;/code&gt;&amp;rsquo;s
type, we see we&amp;rsquo;ll need to head in the other direction:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt;               &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;modifyState&lt;/span&gt;            &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;binding&quot;&gt;Binding&lt;/h2&gt;

&lt;p&gt;If we simplify the types here, the next step should be obvious. (This is
pseudo-Haskell.)&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt;    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;modifyState&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We need some function that, with an &lt;code&gt;f a&lt;/code&gt; and &lt;code&gt;a -&amp;gt; f b&lt;/code&gt;, derive an
&lt;code&gt;f b&lt;/code&gt;. This sounds just like &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt;, the monadic bind operation!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;                    &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modifyState&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That&amp;rsquo;s it &amp;ndash; we&amp;rsquo;ve found our definition for &lt;code&gt;phonemeClassDefinition&lt;/code&gt;!
With some reformatting:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ParsecT&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PhonemeClassMap&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Identity&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;phonemeClassDefinition&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modifyState&lt;/span&gt;
                         &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modifier&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhonemeClass&lt;/span&gt;
                                          &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defn&lt;/span&gt;
                               &lt;span class=&quot;n&quot;&gt;defn&lt;/span&gt;     &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&amp;#39;:&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;many1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anyPhoneme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We&amp;rsquo;ve finished with the hardest parser of the set. In the next post,
we&amp;rsquo;ll tackle the remaining parsers, most of which are simple
combinations of those constructed today.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Parsing sound change rules with Parsec&#58; Part 1</title>
      <link>http://engel.uk.to/2012/sound-change-parsing-bnf-grammar/</link>
      <pubDate>Fri, 14 Dec 2012 00:00:00 -0800</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/sound-change-parsing-bnf-grammar/</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the first post in a tutorial series on applying Parsec in
 historical linguistics. We&amp;rsquo;ll begin by providing a more formal
 description of sound change rule grammars and end by building a
 full-fledged sound change applier.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Historical linguists&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; use a standard grammar to describe a language&amp;rsquo;s
&lt;a href=&quot;http://en.wikipedia.org/wiki/Sound_change&quot;&gt;sound change&lt;/a&gt; over time (&lt;a href=&quot;http://en.wikipedia.org/wiki/Diachronic_linguistics&quot;&gt;diachronically&lt;/a&gt;) or among different
speakers at the same time (&lt;a href=&quot;http://en.wikipedia.org/wiki/Synchronic_linguistics&quot;&gt;synchronically&lt;/a&gt;). Each individual change
can be explained by a simple replacement rule, but often requires a
certain context to occur. An example &lt;em&gt;unconditioned&lt;/em&gt; sound change rule
follows:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r &amp;gt; l
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This rule states that, in some language, the /r/ sound becomes /l/ no
matter the context of the /r/ sound. This rule alone can effectively
describe the change from a morph /fara/ to /fala/, or from /rata/ to
/lata/.&lt;/p&gt;

&lt;p&gt;Most sound change in natural languages, however, are &lt;em&gt;conditional&lt;/em&gt;: they
only occur in certain contexts. We can describe required contexts with
an additional clause in sound change rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;r &amp;gt; l / a_o
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This rule states that /r/ changes to /l/ only when preceded by an /a/
and succeeded by an /o/. It describes a change from /taro/ to /talo/,
but not from /tar/ to /tal/ or /ero/ to /elo/.&lt;/p&gt;

&lt;p&gt;We can describe this sound change rule format as a simple
&lt;a href=&quot;http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form&quot;&gt;BNF grammar&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;rule&amp;gt;          ::= &amp;lt;context&amp;gt; &quot;&amp;gt;&quot; &amp;lt;replacement&amp;gt; [&quot;/&quot; &amp;lt;condition&amp;gt;]
&amp;lt;condition&amp;gt;     ::= &amp;lt;context&amp;gt;_&amp;lt;context&amp;gt;
&amp;lt;context&amp;gt;       ::= (&amp;lt;phoneme&amp;gt; | &amp;lt;phoneme-class&amp;gt;)+
&amp;lt;phoneme&amp;gt;       ::= &amp;lt;lowercase-letter&amp;gt;
&amp;lt;phoneme-class&amp;gt; ::= &amp;lt;uppercase-letter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Close readers will notice that I included in the above grammar the
concept of a &lt;em&gt;phoneme class&lt;/em&gt;. Sound change appliers often accept as
input along with sound change rules a list of phoneme class definitions.
These describe sets of phonemes which, when referenced within a context,
allow any of their members to appear in the specified position.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;V: aeiou
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This line defines a phoneme class &lt;strong&gt;V&lt;/strong&gt; (presumably the &lt;em&gt;vowel&lt;/em&gt; class).
Whenever &lt;strong&gt;V&lt;/strong&gt; appears in a sound change rule, any of /a/, /e/, /i/,
/o/, or /u/ should match.&lt;/p&gt;

&lt;p&gt;Phoneme classes are extremely useful, since most sound changes
(synchronic and diachronic) only apply in certain phonological contexts
rather than standing as a universal fact. Let&amp;rsquo;s amend our grammar so
that we can describe an entire sound change collection:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;file&amp;gt;               ::= (&amp;lt;phoneme-class-defn&amp;gt; &amp;lt;EOL&amp;gt;)* (&amp;lt;rule&amp;gt; &amp;lt;EOL&amp;gt;)+
&amp;lt;phoneme-class-defn&amp;gt; ::= &amp;lt;phoneme-class&amp;gt; &quot;:&quot; &amp;lt;phoneme&amp;gt;+
&amp;lt;rule&amp;gt;               ::= &amp;lt;context&amp;gt; &quot;&amp;gt;&quot; &amp;lt;replacement&amp;gt; [&quot;/&quot; &amp;lt;condition&amp;gt;]
&amp;lt;condition&amp;gt;          ::= &amp;lt;context&amp;gt;_&amp;lt;context&amp;gt;
&amp;lt;context&amp;gt;            ::= (&amp;lt;phoneme&amp;gt; | &amp;lt;phoneme-class&amp;gt;)+
&amp;lt;phoneme&amp;gt;            ::= &amp;lt;lowercase-letter&amp;gt;
&amp;lt;phoneme-class&amp;gt;      ::= &amp;lt;uppercase-letter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the next installment of this tutorial, we&amp;rsquo;ll use this grammar to
build a Parsec parser that can digest sound change rules.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;And conlangers!&lt;a href=&quot;#fnref:1&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Hillis β-reduction in Haskell</title>
      <link>http://engel.uk.to/2012/beta-reduction-in-haskell/</link>
      <pubDate>Sun, 26 Aug 2012 00:00:00 -0700</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/beta-reduction-in-haskell/</guid>
      <description>&lt;p&gt;I decided to rewrite my &lt;a href=&quot;/2012/hillis-beta-reduction-in-clojure&quot;&gt;Hillis β-reduction routine&lt;/a&gt; in Haskell. I
was very pleased to find that the rewrite yielded code much more concise
and less &amp;ldquo;hacky&amp;rdquo; than the original Clojure algorithm.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;haskell&quot;&gt;&lt;span class=&quot;kr&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Beta&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data.Map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- Used to insert or merge map values. Partially apply this function&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- with a merge function and an initial value, then use it in&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;-- `Data.Map.alter`.&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;alterer&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;alterer&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;alterer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- beta-reduce a list of keys and values with a given merge function.&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vals&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vals&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;-- Internal recursive function.&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ord&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alterer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;
                            &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beta&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&amp;#39;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.html&quot;&gt;&lt;code&gt;Data.Map&lt;/code&gt;&lt;/a&gt; turned out to be a lifesaver!&lt;a href=&quot;#fnref:1&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Hillis beta reduction improvements</title>
      <link>http://engel.uk.to/2012/better-hillis-beta-reduction/</link>
      <pubDate>Sun, 08 Jul 2012 00:00:00 -0700</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/better-hillis-beta-reduction/</guid>
      <description>&lt;p&gt;&lt;a href=&quot;/2012/hillis-beta-reduction-in-clojure/&quot;&gt;Last week&lt;/a&gt; I introduced the concept of Hillis beta reduction and provided an example implementation in Clojure. There were a few caveats to this implementation, however, mostly stemming from the fact that I &amp;beta;-reduced with sequences and vectors rather than the native &amp;ldquo;xectors&amp;rdquo; of Hillis&amp;rsquo; system. With the risk of adding even more complexity to the demonstration, I&amp;rsquo;d like to attempt to rectify some of these problems using a few extra tools to transform our data.&lt;/p&gt;

&lt;h2 id=&quot;xectors&quot;&gt;Xectors&lt;/h2&gt;

&lt;p&gt;I won&amp;rsquo;t provide much detail at all on the xector data type, as I will inevitably botch the majority of the facts. If you&amp;rsquo;re at all interested in parallel computing, I recommend checking out Hillis&amp;rsquo; book, &lt;a href=&quot;http://www.amazon.com/gp/product/0262580977/ref=as_li_tf_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0262580977&amp;amp;linkCode=as2&amp;amp;tag=blog0cbb-20&quot;&gt;The Connection Machine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For our purposes, we can consider a xector to be equivalent to a Clojure map&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. We can easily redesign our Hillis &amp;beta;-reduction function to take maps as input, but who would want to convert a sequence to a map whenever using the function?&lt;/p&gt;

&lt;h3 id=&quot;the-xector-monad&quot;&gt;The Xector monad&lt;/h3&gt;

&lt;p&gt;For this issue we can design a small &lt;a href=&quot;http://en.wikipedia.org/wiki/Monad_(functional_programming)&quot;&gt;monad&lt;/a&gt; which deliberately breaks the monad laws (cowboy monad?) for demonstration purposes&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. The monad will convert provided seqs into an internal map (xector) representation for use in the &amp;beta;-function and (here&amp;rsquo;s the law-breaking part) leave them as maps when returning results. We could be proper and return the same seq type that was provided, but that would essentially destroy the purpose of the &amp;beta;-reduction in the first place!&lt;/p&gt;

&lt;p&gt;Without further ado:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;clojure.algo.monads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defmonad&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector-m&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Xector a -&amp;gt; a&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;m-result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m-result-xector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;count &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vals &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;nv&quot;&gt;xector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

   &lt;span class=&quot;c1&quot;&gt;;; a -&amp;gt; (Xector b -&amp;gt; Xector c) -&amp;gt; Xector c&lt;/span&gt;
   &lt;span class=&quot;nv&quot;&gt;m-bind&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;m-bind-xector&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sequential?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;into &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map-indexed&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;vector &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                        &lt;span class=&quot;nv&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice the cheating in &lt;code&gt;m-result&lt;/code&gt;: we return constant values as expected, but non-constant values (i.e., maps made from seqs) are kept as maps.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;m-bind&lt;/code&gt;, we convert any type of seq into a map, and keep any other constant value (in our case, we&amp;rsquo;ll use numbers) unmodified&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;beta-reduction-redux&quot;&gt;&amp;beta;-reduction-redux&lt;/h2&gt;

&lt;p&gt;We define a new multimethod &lt;code&gt;xvals&lt;/code&gt; which dispatches on the result of &lt;code&gt;map?&lt;/code&gt;&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. This aligns with the result of the monad bind we defined earlier: for any &lt;code&gt;a&lt;/code&gt; of &lt;code&gt;Xector a&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt; will be either a map or a constant.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defmulti &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xvals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;map?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xvals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;vals &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defmethod &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;xvals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beta&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; (a -&amp;gt; b) -&amp;gt; Xector c -&amp;gt; Xector d&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; (a -&amp;gt; b) -&amp;gt; Xector c -&amp;gt; Xector d -&amp;gt; Xector e&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xvals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xvals&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
              &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
           &lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;new-val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;contains? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                           &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;new-val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can perform &amp;beta;-reduction on seqs by binding them inside our &lt;code&gt;xector-m&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;domonad&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector-m&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; {X 1, Z 7}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Traditional folds can now return the expected values without a wrapping map:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;domonad&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector-m&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;hillis-arity-function&quot;&gt;Hillis&amp;rsquo; arity function&lt;/h3&gt;

&lt;p&gt;Now that we have a better-ported version of the beta function, I can present a fascinating application also imagined by Hillis later in his paper. It uses both the one- and two-argument forms of the beta function: it simultaneously folds multiple maps into a single map, and then folds that single map to a single value. As always, the code speaks more clearly than I can:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Return the highest arity of the sequence (i.e., the number of times&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;; the most often occurring element appears).&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;domonad&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector-m&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;seq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the inner &amp;beta;-reduce, we reduce a set of keys to the same constant value of 1. When duplicate keys (duplicate occurrences of a value in the provided seq) are found, the value 1 is combined with another value 1 using the function &lt;code&gt;+&lt;/code&gt;, forming a count of 2! This process repeats until the entire provided seq has been digested. Here&amp;rsquo;s a look at the inner &amp;beta;-reduction by itself (notice that its output matches that of &lt;code&gt;frequencies&lt;/code&gt;!):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;domonad&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xector-m&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
          &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; {2 4, 3 1, 5 1, 8 2}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;where-from-here&quot;&gt;Where from here?&lt;/h3&gt;

&lt;p&gt;To be frank: not a clue! I am having trouble thinking of names for the process, let alone applications. It will most likely remain nothing more than a &amp;ldquo;thought experiment,&amp;rdquo; as I said in my previous post. Let me know in the comments below if you have any thoughts!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=blog0cbb-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0262580977&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Ignoring all the parallel-processing fun that comes along with xectors, yes.&lt;a href=&quot;#fnref:1&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;I still don&amp;rsquo;t fully understand monads, so I may actually be breaking more laws than I intend.&lt;a href=&quot;#fnref:2&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;I experimented with a &lt;code&gt;ConstantXector&lt;/code&gt; type and a &lt;code&gt;:constant&lt;/code&gt; metadata key, but both of these methods proved much less elegant than simply leaving the value alone.&lt;a href=&quot;#fnref:3&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;Dispatches on &amp;ldquo;mappiness?&amp;rdquo;&lt;a href=&quot;#fnref:4&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Hillis beta reduction in Clojure</title>
      <link>http://engel.uk.to/2012/hillis-beta-reduction-in-clojure/</link>
      <pubDate>Tue, 03 Jul 2012 00:00:00 -0700</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/hillis-beta-reduction-in-clojure/</guid>
      <description>&lt;p&gt;Danny Hillis&amp;rsquo; seminal work &lt;a href=&quot;http://www.amazon.com/gp/product/0262580977/ref=as_li_tf_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0262580977&amp;amp;linkCode=as2&amp;amp;tag=blog0cbb-20&quot;&gt;The Connection Machine&lt;/a&gt; introduced, among many other things, the concept of &amp;ldquo;beta reduction&amp;rdquo; on vectors&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (I dub this &amp;ldquo;Hillis beta reduction&amp;rdquo; so as not to confuse the term with traditional &lt;a href=&quot;http://en.wikipedia.org/wiki/Lambda_calculus#Beta_reduction&quot;&gt;beta reduction&lt;/a&gt; in the lambda calculus). I found this particular idea fascinating and still applicable today, if only as a quick thought experiment.&lt;/p&gt;

&lt;p&gt;Hillis asserted that the everyday &lt;a href=&quot;http://en.wikipedia.org/wiki/Fold_(higher-order_function)&quot;&gt;fold / reduce routines&lt;/a&gt; that we have all come to know and love are merely a subset of a larger scheme of operations that can be performed on ordered data structures. The overarching process is named the &amp;ldquo;beta function,&amp;rdquo; and accepts one function and two vectors as arguments. The result of this function is the combination of the two vectors into a map, using the first vector to form the map&amp;rsquo;s values and the second vector to form the map&amp;rsquo;s keys. When duplicate keys are found, the provided function is used to &amp;ldquo;combine&amp;rdquo; the corresponding values. It&amp;rsquo;s an interesting process that&amp;rsquo;s much easier to understand given an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Z&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; {X 1, Z 7}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using the positions of each element to match keys and values of the map to be formed, the beta function pulls together data like a zip function. When the duplicate key &lt;code&gt;Z&lt;/code&gt; is encountered twice, the two values are combined using the &lt;code&gt;+&lt;/code&gt; function we provided, and the final value corresponding to the key &lt;code&gt;Z&lt;/code&gt; in the map is &lt;code&gt;(+ 2 5)&lt;/code&gt;, or &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What is traditional list folding, then? Why, it&amp;rsquo;s just beta reduction with a certain constant second argument:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; {1 8}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When we provide the beta function with the same key for every value (&lt;code&gt;1&lt;/code&gt;, in this case), all values are combined to the same key using the provided function. This is reduction in a different form!&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Below is an implementation of Hillis&amp;rsquo; beta function in Clojure. I included a shorthand form of the function in which a two-argument call will give the same result as a call to &lt;code&gt;reduce&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;+ &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; =&amp;gt; 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Feel free to play around!&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;clojure&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;defn &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;beta&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;beta&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;repeat &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;loop &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;or &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nil? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;new-val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;contains? &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;get &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                         &lt;span class=&quot;nv&quot;&gt;e1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;recur&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;assoc &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;e2&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;new-val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;first &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rest &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;http://www.assoc-amazon.com/e/ir?t=blog0cbb-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0262580977&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;For simplicity&amp;rsquo;s sake, I deliberately ripped out Hillis&amp;rsquo; concept of beta reduction from its containing system of parallel processing with xectors. References to this particular domain have been shamelessly replaced with Clojure-specific terms.&lt;a href=&quot;#fnref:1&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;You may notice that this alternate fold returns &lt;code&gt;{1 8}&lt;/code&gt; rather than a simple &lt;code&gt;8&lt;/code&gt;. This is due to my somewhat-haphazard readaptation of Hillis&amp;rsquo; concept for Clojure: the &lt;code&gt;{1 8}&lt;/code&gt; that is returned is technically correct within Hillis&amp;rsquo; system of xectors, but is not convenient for those of us living in a von Neumann world. I experimented in using a xector monad as a sort of shim to better integrate beta-reduction into Clojure, but did not develop it far enough to make it merit more than a mention in a footnote.&lt;a href=&quot;#fnref:2&quot; rel=&quot;reference&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Disabling electric indenting in Emacs modes</title>
      <link>http://engel.uk.to/2012/disabling-electric-indent-mode/</link>
      <pubDate>Mon, 02 Jul 2012 00:00:00 -0700</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/disabling-electric-indent-mode/</guid>
      <description>&lt;p&gt;I am just getting settled in with &lt;a href=&quot;http://orgmode.org&quot;&gt;Org Mode&lt;/a&gt; for Emacs and am constantly amazed at its versatility and wide feature set. One problem has been bugging me in Org for quite a while now, though: &lt;code&gt;electric-indent-mode&lt;/code&gt;, which I use for auto-indentation when programming, gets in the way by auto-indenting Org headers.&lt;/p&gt;

&lt;p&gt;My annoyance reached a critical point earlier this morning, and so I set off in search of a fix to disable electric indenting &amp;ldquo;mode-locally&amp;rdquo; &amp;mdash; that is, disable the mode in Org buffers but not in buffers of any other mode. The catch with &lt;code&gt;electric-indent-mode&lt;/code&gt; is that it is a global minor mode &amp;mdash; something that is enabled once and assumed to be necessary for all buffers.&lt;/p&gt;

&lt;p&gt;After a bit of searching, however, I was glad to find that the author of the mode had left in a backdoor for customizing its functionality. Meet &lt;code&gt;electric-indent-functions&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Special hook run to decide whether to auto-indent.
Each function is called with one argument (the inserted char), with point right after that char, and it should return t to cause indentation, `no-indent&amp;rsquo; to prevent indentation or nil to let other functions decide.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perfect! The default value for this variable (as of Emacs 24.0.92.1) is &lt;code&gt;nil&lt;/code&gt;, so I made the choice to recklessly overwrite this variable at a &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/emacs/Locals.html&quot;&gt;buffer-local level&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enough technoblabber; here&amp;rsquo;s the fix. Add the following code into an Emacs Lisp file that gets run on initialization:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;cl&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;org-mode-hook&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;make-local-variable&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;electric-indent-functions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                 &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;no-indent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can find the latest version of my Org mode config in my &lt;a href=&quot;https://github.com/hans/dotfiles/blob/master/emacs.d/scripts/org.el&quot;&gt;&lt;code&gt;dotfiles&lt;/code&gt; repo&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    
    <item>
      <title>Post excerpts in Jekyll</title>
      <link>http://engel.uk.to/2012/jekyll-excerpts/</link>
      <pubDate>Sat, 21 Jan 2012 00:00:00 -0800</pubDate>
      <author>engel@engel.uk.to (Hans Engel)</author>
      <guid>http://engel.uk.to/2012/jekyll-excerpts/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s a &lt;a href=&quot;http://www.jacquesf.com/2011/03/creating-excerpts-in-jekyll-with-wordpress-style-more-html-comments/&quot;&gt;fairly simple method&lt;/a&gt; for creating WordPress-like post excerpts in Jekyll using a &lt;code&gt;&amp;lt;!-- more --&amp;gt;&lt;/code&gt; tag, but unfortunately it requires the installation of a Jekyll plugin, a feature unavailable on a GitHub-hosted Jekyll instance.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s a bored geek like me to do? Find another way! &lt;!-- more --&gt; The exact same excerpt functionality linked to earlier can be replicated by composing a few &lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers&quot;&gt;Liquid filters&lt;/a&gt; in the site layout code, like so:&lt;/p&gt;

&lt;pre&gt;&amp;#123;{ post.content | split: '&amp;lt;!-- more --&amp;gt;' | first }}&lt;/pre&gt;

&lt;p&gt;This little bit of code will output the content of a post until it sees a &lt;code&gt;&amp;lt;!-- more --&amp;gt;&lt;/code&gt; tag inside the post content. Just insert the &lt;code&gt;&amp;lt;!-- more --&amp;gt;&lt;/code&gt; tag into your posts wherever you&amp;rsquo;d like them to be cut off.&lt;/p&gt;

&lt;p&gt;You can see this snippet in action in my &lt;a href=&quot;/&quot;&gt;site index template&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    

  </channel>
</rss>
