<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4650294074444534066</id><updated>2012-01-17T12:47:11.146-08:00</updated><category term='the &apos;real world&apos;'/><category term='difference lists'/><category term='monadplus'/><category term='design patterns'/><category term='poem'/><category term='unification'/><category term='arrow'/><category term='java'/><category term='memoization'/><category term='monad'/><category term='maybe'/><category term='monoid'/><category term='combinatory logic'/><category term='monad transformers'/><category term='parsing'/><category term='prolog'/><category term='on-the-job'/><category term='housekeeping'/><category term='pensées'/><category term='comonad'/><category term='fuzzy'/><category term='rule-based programming'/><category term='license'/><category term='reading list'/><category term='nondeterminism'/><category term='knowledge engineering'/><title type='text'>Typed Logic</title><subtitle type='html'>Incorporates strong typing over predicate logic programming, and, conversely, incorporates predicate logic programming into strongly typed functional languages.  The style of predicate logic is from Prolog; the strongly typed functional language is Haskell.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-7366069983773698727</id><published>2011-09-25T19:22:00.000-07:00</published><updated>2011-10-03T03:48:44.516-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><title type='text'>Monads in Java</title><content type='html'>  &lt;p&gt;  A while back Brent Yorgey &lt;a href='http://byorgey.wordpress.com'&gt;http://byorgey.wordpress.com&lt;/a&gt;  posted a menagerie of types. A very nice survey of types in Haskell, including, among other things, the monadic types.  &lt;p&gt;  A reader posted a question, framed with 'you know, it'd be a lot easier for me to understand monads if you provided an implementation in Java.'&lt;a name='mark1'&gt;[&lt;/a&gt;&lt;a href='#endnote1'&gt;1&lt;/a&gt;]  &lt;p&gt;  Well, that reader really shouldn't have done that.  &lt;p&gt;  Really.  &lt;p&gt;  Because it got me to thinking, and dangerous things comes out of geophf's thoughts ... like monads in Java.  &lt;p&gt;  Let's do this.  &lt;p&gt;  &lt;h2&gt;Problem Statement&lt;/h2&gt;  &lt;p&gt;  Of course, you just don't write monads for Java. You need some motivation. What's my motivation?  &lt;p&gt;  Well, I kept running up against the Null Object pattern, because I kept running up against null in the Java runtime, because there's a whole lot of optionality in the data sets I'm dealing with, and instead of using the Null Object, null is used to represent absence.  &lt;p&gt;  Good choice?  &lt;p&gt;  Well, it's expedient, and that's about the best I can say for that.  &lt;p&gt;  So I had to keep writing the Null Object pattern for each of these optional element types I encountered.  &lt;p&gt;  I encounter quite a few of them ... 2,100 of them and counting.  &lt;p&gt;  So I generalized the Null object pattern using generic types, and that worked fine ...  &lt;p&gt;  But I kept looking at the pattern. The generalization of the Null Object pattern is &lt;code&gt;&lt;tt&gt;Nothing&lt;/tt&gt;&lt;/code&gt;, and a present instance is &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt; that something.  &lt;p&gt;  I had implemented non-monadic &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  And the problem with that is that none of the power of &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, as a &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;, is available to a generalized Null Object pattern.  &lt;p&gt;  Put another way: I wish to do something given that something is present.  &lt;p&gt;  Put another-another way: &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  So, after a long hard look ('do I &lt;em&gt;really&lt;/em&gt; want to implement monads? Can't I just settle for 'good enough' ... that really &lt;em&gt;isn't&lt;/em&gt; good enough?), I buckled down to do the work of implementing not just &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; (heh: '&lt;code&gt;&lt;tt&gt;Just Maybe&lt;/tt&gt;&lt;/code&gt;'), but &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; itself.  &lt;p&gt;  Did it pay off? Yes, but wait and see. First the implementation. But even before that, let's review what a monad is.  &lt;p&gt;  &lt;h2&gt;What the Hell is a Monad?&lt;/h2&gt;  &lt;p&gt;  Everybody seems to ask this question when first encountering monads, and everybody seems to come up with their own explanations, so we have tutorials that explain Monads as things as far-ranging from spacesuits to burritos.  &lt;p&gt;  My own explanation is to punt ... to category theory.  &lt;p&gt;  A monad is simply a triple (that's why it's called a monad, ... because it's a triple), defined thusly:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;(T, &amp;eta;, &amp;mu;)&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  Simple right?  &lt;p&gt;  &lt;em&gt;Don't leave me!&lt;/em&gt;  &lt;p&gt;  Okay, yes. I understand you are rolling your eyes and saying 'well, that's all Greek to me.'  &lt;p&gt;  So allow me to explain in plain language the monad.  &lt;p&gt;  Monad is the triple &lt;code&gt;&lt;tt&gt;(T, &amp;eta;, &amp;mu;)&lt;/tt&gt;&lt;/code&gt; where  &lt;p&gt;  &lt;ul&gt;&lt;li&gt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt; is the Monad &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;&amp;eta;&lt;/tt&gt;&lt;/code&gt; is the unit function that &lt;em&gt;lifts&lt;/em&gt; an ordinary object (a &lt;em&gt;unit&lt;/em&gt;) into the Monad functor; and,&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;&amp;mu;&lt;/tt&gt;&lt;/code&gt; is the join function that takes a composed monad &lt;code&gt;&lt;tt&gt;M (M a)&lt;/tt&gt;&lt;/code&gt; and returns the simplified type of the composition, or &lt;code&gt;&lt;tt&gt;M a&lt;/tt&gt;&lt;/code&gt;.&lt;/li&gt;  &lt;/ul&gt;  &lt;p&gt;  And that is (simply) what the hell a Monad is. What a monad can do ... well, there are articles galore about that, and, later, I will provide examples of what Monad gives us ... in Java, no less.  &lt;p&gt;  &lt;h2&gt;The Implementation&lt;/h2&gt;  &lt;p&gt;  We need to work our way up to Monad. There's a whole framework, a way of thinking, a context, that needs to be in place for Monad to be effective or even to exist. Monad is 'happy' in the functional world, so we need to implement functions.  &lt;p&gt;  Or more correctly, 'functionals' ... in Haskell, they are called 'Functors.'  &lt;p&gt;  A functor is a container, and the function of functors is to take an ordinary function, which we write: &lt;code&gt;f: a &amp;rarr; b&lt;/code&gt; (pronounced "the function &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; from (type) &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt; to (type) &lt;code&gt;&lt;tt&gt;b&lt;/tt&gt;&lt;/code&gt;" and means that &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; takes an argument of type &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt; and returns a result of type &lt;code&gt;&lt;tt&gt;b&lt;/tt&gt;&lt;/code&gt;), and give a function &lt;code&gt;g: Functor a &amp;rarr; Functor b&lt;/code&gt;.  &lt;p&gt;  Functor basically is a container for the function &lt;code&gt;fmap: Functor f &amp;rArr; (a &amp;rarr; b) &amp;rarr; (f a &amp;rarr; f b)&lt;/code&gt;  &lt;p&gt;  Well, is Functor the fundamental type? Well, yes and no.  &lt;p&gt;  It is, given that we have functions defined. In Java, we don't have that. We have methods, yes, but we don't have free-standing functions. Let's amend that issue:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public interface&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T1&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T2&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;T2&lt;/tt&gt;&lt;/code&gt; apply(&lt;code&gt;&lt;tt&gt;T1&lt;/tt&gt;&lt;/code&gt; arg) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;  };&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  And what's this Failure thingie? It's simply a functional exception, so:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;(&lt;code&gt;&lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt; string) { &lt;br /&gt;          &lt;jkey&gt;super&lt;/jkey&gt;(string); &lt;br /&gt;      }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      /// and the serialVersionUID for serialization; your IDE can define that&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  I call a Function 'Applicable' because in functional languages that's what you do: &lt;em&gt;apply&lt;/em&gt; a function on (type) a to get (type) b. And, using Java Generics terminology, type a is &lt;code&gt;T1&lt;/code&gt; and type b is &lt;code&gt;T2&lt;/code&gt;.  So we're using pure Java to write pure Java code and none will be the wiser that we're actually doing Category Theory via a Haskell implementation ... in Java, right?  &lt;p&gt;  Right.  &lt;p&gt;  So, now we have functions (Applicable), we can provide the declaration of the Functor type:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public interface&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;       &lt;jkey&gt;public&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T1&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;? &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;,&lt;br /&gt;                              ? &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T1&lt;/tt&gt;&lt;/code&gt;&gt;&gt;&lt;br /&gt;          fmap(&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T1&lt;/tt&gt;&lt;/code&gt;&gt; f) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt; arg() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  The above definition of &lt;code&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/code&gt; is the same declaration (in Java) as its functional declaration: it takes a function &lt;code&gt;f: a &amp;rarr; b&lt;/code&gt; and gives a function &lt;code&gt;g: Functor a &amp;rarr; Functor b&lt;/code&gt;  &lt;p&gt;  Okay, we're half-way there. A &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; is a &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;, and we have &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt; declared.  &lt;p&gt;  The unit function, &lt;code&gt;&lt;tt&gt;&amp;eta;&lt;/tt&gt;&lt;/code&gt;, comes for free in Java: it's called &lt;code&gt;&lt;tt&gt;new&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  So that leaves the join function &lt;code&gt;&lt;tt&gt;&amp;mu;&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  And defining &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; for a specific monad is simple. Join for the list monad is append. Join for the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; monad and the ID monad is &lt;code&gt;&lt;tt&gt;arg&lt;/tt&gt;&lt;/code&gt;. What about &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; for just &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;?  &lt;p&gt;  Well, there is no definition of such, but we can declare its type:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public interface&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Joinable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;F&lt;/tt&gt;&lt;/code&gt;, ?&gt; join() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  &lt;em&gt;Too easy!&lt;/em&gt; you complain.  &lt;p&gt;  Well, isn't it supposed to be? Join is simply a function that takes a functor and returns functor.  &lt;p&gt;  The trick is that we have to ensure that &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt; is of type &lt;code&gt;&lt;tt&gt;Functor&amp;lt;F, ?&gt;&lt;/tt&gt;&lt;/code&gt;, and we leave that an implementation detail for each specific monad implementing &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  That was easy!&amp;trade;  &lt;p&gt;  &lt;h2&gt;Monad&lt;/h2&gt;  &lt;p&gt;  So now that we have all the above, Functor, Join, and Unit, we have Monad:  &lt;p&gt;  ... BUT WAIT!  &lt;p&gt;  And here's the interlude of where the power of Monad comes in: bind.  &lt;p&gt;  What is &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt;? Bind is a function that says: do something in the monadic domain.  &lt;p&gt;  Really, that sounds boring, right? But it's a very powerful thing. Because once we are in the monadic domain, we can guarantee things that we cannot in Java category (if there is such).  &lt;p&gt;  (There is. I just declared it.)&lt;a name='mark2'&gt;[&lt;/a&gt;&lt;a href='#endnote2'&gt;2&lt;/a&gt;]  &lt;p&gt;  So, in the monadic domain, a function thus bound can be guaranteed to, e.g., be working with an instance and not a null.  &lt;p&gt;  Guaranteed.  &lt;p&gt;  AND! ...  &lt;p&gt;  Well, what is bind?  &lt;p&gt;  Bind is a function that takes an ordinary value and returns a result in the monadic domain:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Monad m &amp;rArr; bind: a &amp;rarr; m b&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  So the 'AND!' of this is that &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; can be chained ... meaning we can go from guarantee to guarantee, threading a safe computation from start to finish.  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; gives us &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  And the beauty of &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;? &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; comes for free, for once &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; is defined, &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; can be defined in terms of &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt;:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Monad m &amp;rArr; bind (f: a &amp;rarr; m b) (m a) = join ((fmap f) (m a))&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  Do you see what is happening here? We are using &lt;code&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/code&gt; to lift the function &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; one step higher into the monadic domain, so &lt;code&gt;&lt;tt&gt;fmap f&lt;/tt&gt;&lt;/code&gt; gives the function &lt;code&gt;&lt;tt&gt;Monad m &amp;rArr; g: m a &amp;rarr; m (m b)&lt;/tt&gt;&lt;/code&gt; so we are not actually passing in a value of type &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt;, we are passing in the Monad &lt;code&gt;&lt;tt&gt;m a&lt;/tt&gt;&lt;/code&gt;, and then we get back a type of &lt;code&gt;&lt;tt&gt;m (m b)&lt;/tt&gt;&lt;/code&gt; which then &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; does it magic to simplify to the monadic type &lt;code&gt;&lt;tt&gt;m b&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  So to the outside world, it looks like we are passing in an &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt; to get an &lt;code&gt;&lt;tt&gt;m b&lt;/tt&gt;&lt;/code&gt; but this definition allows monadic chaining, for &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt; becomes &lt;code&gt;&lt;tt&gt;m a&lt;/tt&gt;&lt;/code&gt; and then &lt;code&gt;&lt;tt&gt;m (m b)&lt;/tt&gt;&lt;/code&gt; is simplified to &lt;code&gt;&lt;tt&gt;m b&lt;/tt&gt;&lt;/code&gt; that &amp;mdash; and here's the kicker &amp;mdash; is passed to the next monadically bound function.  &lt;p&gt;  You can chain this as far as you'd like:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;m a &gt;&gt;= f &gt;&gt;= g &gt;&gt;= &lt;/tt&gt;.&lt;tt&gt;&lt;/tt&gt;.&lt;tt&gt;&lt;/tt&gt;.&lt;tt&gt; &gt;&gt;= h &amp;rarr; m z&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  And since the computation occurs in the monadic domain, you are guaranteed the promise of that domain.  &lt;p&gt;  There is the power of monadic programming.  &lt;p&gt;  Given that explanation, and remembering that &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; can be defined in terms of &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt;, let's define Monad:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public abstract class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; &lt;jkey&gt;implements&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Joinable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; bind(&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt; f) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;          &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt;&gt; a&lt;br /&gt;              = (&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt;&gt;) fmap(f);&lt;br /&gt;          &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt; mmonad = a.apply(&lt;jkey&gt;this&lt;/jkey&gt;);&lt;br /&gt;          &lt;jkey&gt;return&lt;/jkey&gt; (&lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;) mmonad.join();&lt;br /&gt;      }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;M&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; fail(&lt;code&gt;&lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt; ex) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;          &lt;jkey&gt;throw new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;(ex);&lt;br /&gt;      }&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  The bind implementation is exactly as previously discussed: &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; is the application of the &lt;code&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/code&gt; of &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; with the &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt;ed result returned. So, we simply define &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; for subclasses, usually a trivial definition, and we have the power of &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; &lt;em&gt;automagically!&lt;/em&gt;  &lt;p&gt;  Now &lt;code&gt;&lt;tt&gt;fail&lt;/tt&gt;&lt;/code&gt; is an interesting beast in subclasses, because in the monadic domain, failure is not always a bad thing, or even an exceptional one, and can be quite, and very, useful.  Some examples, fail represents 'zero' in the monadic domain, so 'failure' for list is the empty list, and 'failure' for &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; is &lt;code&gt;&lt;tt&gt;Nothing&lt;/tt&gt;&lt;/code&gt;.  So, when failure occurs, the computation can continue gracefully and not always automatically abort from the computation, which happens with the try/catch paradigm.  &lt;p&gt;  There you have it: Monads in Java!  &lt;p&gt;  &lt;h2&gt;The rest of the story: ... Maybe&lt;/h2&gt;  &lt;p&gt;  So, we could've ended this article right now, and you have everything you need to do monadic programming in Java. But so what? A programming paradigm isn't useful if there are no practical applications. So let's give you one: &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; is a binary type, it is either &lt;code&gt;&lt;tt&gt;Nothing&lt;/tt&gt;&lt;/code&gt; or &lt;code&gt;&lt;tt&gt;Just x&lt;/tt&gt;&lt;/code&gt; where &lt;code&gt;&lt;tt&gt;x&lt;/tt&gt;&lt;/code&gt; is whatever value that is what we're really looking for (as opposed to the usual case in Java: &lt;jkey&gt;null&lt;/jkey&gt;).  &lt;p&gt;  So, let's define the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; type in Java.  &lt;p&gt;  First is the protocol that extends the &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public abstract class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;  &lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  Do you see how the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; type declares &lt;em&gt;itself&lt;/em&gt; as a &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; in its own definition? I just love that.  &lt;p&gt;  Anyway.  &lt;p&gt;  As mentioned before, &lt;code&gt;&lt;tt&gt;fail&lt;/tt&gt;&lt;/code&gt; for &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; is &lt;code&gt;&lt;tt&gt;Nothing&lt;/tt&gt;&lt;/code&gt;:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; fail(&lt;code&gt;&lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt; ex) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;          &lt;jkey&gt;return&lt;/jkey&gt; (&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;) &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  (&lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; is a constant in &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; to be defined later. Before we define it ('it' being &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;), recall that a &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; is a &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt; so we have to define &lt;code&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/code&gt;. Let's do that now)  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;protected abstract&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;br /&gt;              mbBind(&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt; arg) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;, &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt;&lt;br /&gt;                  fmap(&lt;jkey&gt;final&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; f) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;          &lt;jkey&gt;return new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;, &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt;() {&lt;br /&gt;              &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; apply(&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt; arg) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;                  &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt; liFted =&lt;br /&gt;                          &lt;jkey&gt;new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt;() {&lt;br /&gt;                      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; apply(&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt; arg) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;                          &lt;jkey&gt;return&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.pure(f.apply(arg));&lt;br /&gt;                      }&lt;br /&gt;                  };&lt;br /&gt;                  &lt;jkey&gt;return&lt;/jkey&gt; (&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;)arg.mbBind(liFted);&lt;br /&gt;              }&lt;br /&gt;          };&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  No surprises here. &lt;code&gt;&lt;tt&gt;fmap&lt;/tt&gt;&lt;/code&gt; lifts the function &lt;code&gt;&lt;tt&gt;f: a &amp;rarr; b&lt;/tt&gt;&lt;/code&gt; to &lt;code&gt;&lt;tt&gt;Maybe m &amp;rArr; g: m a &amp;rarr; m b&lt;/tt&gt;&lt;/code&gt; where in this case the &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt; is a &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;, and this case, that &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; is &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.&lt;a name='mark3'&gt;[&lt;/a&gt;&lt;a href='#endnote3'&gt;3&lt;/a&gt;]  &lt;p&gt;  There is the small issue(s) of what the &lt;jkey&gt;static&lt;/jkey&gt; method &lt;code&gt;&lt;tt&gt;pure&lt;/tt&gt;&lt;/code&gt; and the method &lt;code&gt;&lt;tt&gt;mbBind&lt;/tt&gt;&lt;/code&gt; are, but these depend on the definitions of the subclasses &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; and &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt;, so let's define them now.  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;public static final&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;?&gt; &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; = &lt;jkey&gt;new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;() {&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt; toString() {&lt;br /&gt;              &lt;jkey&gt;return&lt;/jkey&gt; "Nothing";&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Object&lt;/tt&gt;&lt;/code&gt; arg() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;              &lt;jkey&gt;throw new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;("Cannot extract a value from Nothing.");&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Functor&lt;/tt&gt;&lt;/code&gt; join() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;              &lt;jkey&gt;return this&lt;/jkey&gt;;&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;protected&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; mbBind(&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt; f) {&lt;br /&gt;              &lt;jkey&gt;return this&lt;/jkey&gt;;&lt;br /&gt;          }&lt;br /&gt;      };&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  Trivial definition, as the Null Object pattern is trivial. But do note that the &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; operation &lt;em&gt;does not&lt;/em&gt; perform the &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; computation, but skips it, returning &lt;code&gt;&lt;tt&gt;Nothing&lt;/tt&gt;&lt;/code&gt;, and forwarding the computation.  This is expected behavior, for:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Nothing &gt;&gt;= f &amp;rarr; Nothing&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  The definition of the internal class &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt; is nearly as simple:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;public final static class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;J&lt;/tt&gt;&lt;/code&gt;&gt; &lt;jkey&gt;extends&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;J&lt;/tt&gt;&lt;/code&gt;&gt; {&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt;(&lt;code&gt;&lt;tt&gt;J&lt;/tt&gt;&lt;/code&gt; obj) {&lt;br /&gt;              _unit = obj;&lt;br /&gt;          }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;?&gt; join() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;              &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;                  &lt;jkey&gt;return&lt;/jkey&gt; (&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;?&gt;)_unit;&lt;br /&gt;              } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;ClassCastException&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;                  &lt;jkey&gt;throw new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt;("Joining on a flat structure!");&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt; toString() {&lt;br /&gt;              &lt;jkey&gt;return&lt;/jkey&gt; "Just " + _unit;&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Object&lt;/tt&gt;&lt;/code&gt; arg() &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;              &lt;jkey&gt;return&lt;/jkey&gt; _unit;&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;protected&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;br /&gt;                  mbBind(&lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;J&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;&gt; f) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;              &lt;jkey&gt;return&lt;/jkey&gt; (&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;)f.apply(_unit);&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;private final&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;J&lt;/tt&gt;&lt;/code&gt; _unit;&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  As you can see, the slight variation to &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; for &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt; is that &lt;code&gt;&lt;tt&gt;join&lt;/tt&gt;&lt;/code&gt; returns the &lt;code&gt;&lt;tt&gt;_unit&lt;/tt&gt;&lt;/code&gt; value if it's the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; type (and throws a &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; if it isn't), and &lt;code&gt;&lt;tt&gt;mbBind&lt;/tt&gt;&lt;/code&gt; applies the monadic function &lt;code&gt;&lt;tt&gt;f&lt;/tt&gt;&lt;/code&gt; to the &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt; value.  &lt;p&gt;  And with the definition of &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt; we get the &lt;jkey&gt;static&lt;/jkey&gt; method &lt;code&gt;&lt;tt&gt;pure&lt;/tt&gt;&lt;/code&gt;:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;public static&lt;/jkey&gt; &amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt; pure(&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt; x) {&lt;br /&gt;          &lt;jkey&gt;return new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;T&lt;/tt&gt;&lt;/code&gt;&gt;(x);&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  And then we close out the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; implementation with:  &lt;p&gt;  &lt;jcode&gt;}&lt;/jcode&gt;  &lt;p&gt;  Simple.  &lt;p&gt;  &lt;h2&gt;Practical Example&lt;/h2&gt;  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; is useful for any semideterministic programming, that is: where something may be true, or it may not be. But the question I keep getting, from Java coders, is this: "I have these chains of getter methods in my web interface to my data objects to set a result, but I often have &lt;jkey&gt;null&lt;/jkey&gt;s in some values gotten along the chain. How do I set the value from what I've gotten, or do nothing if there's a &lt;jkey&gt;null&lt;/jkey&gt; along the way."  &lt;p&gt;  "Fine, no problems ..." I begin, but then they interrupt me.  &lt;p&gt;  "No, I'm not done yet! I have like tons of these chained statements, and I don't want to abort on the first one that throws a &lt;code&gt;&lt;tt&gt;NullPointerException&lt;/tt&gt;&lt;/code&gt;, I just want to pass through the statement with the &lt;jkey&gt;null&lt;/jkey&gt; gracefully and continue onto the next assignment. Can your weirdo stuff do that?"  &lt;p&gt;  &lt;em&gt;Weirdo stuff? Excusez moi?&lt;/em&gt;  &lt;p&gt;  I don't feel it's &lt;em&gt;apropos&lt;/em&gt; that functionally pure languages have no (mutable) assignment, as that throws provability out the window and is therefore the root of all evil.  &lt;p&gt;  No matter how sorely tempted I am.  &lt;p&gt;  So, instead I say: "Yeah, that's a bigger problem &lt;em&gt;[soto voce: so you should switch to Haskell!],&lt;/em&gt; but the same solution applies."&lt;a name='mark4'&gt;[&lt;/a&gt;&lt;a href='#endnote4'&gt;4&lt;/a&gt;]  &lt;p&gt;  So, let's go over the problem and a set of solutions.  &lt;p&gt;  The problem is something like:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;jkey&gt;&lt;br /&gt;  try&lt;/jkey&gt; {&lt;br /&gt;      foo.setD(getA().getB().getC().getD());&lt;br /&gt;      foo.setE(getA().getB().getC().getE());&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      bar.setJ(getF().getG().getH().getJ());&lt;br /&gt;      bar.setM(getF().getG().getK().getM());&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      // and ... oh, more than 2000 more assignments ... 'hypothetically'&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;  } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;      ex.printStackTrace();&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  And the problem is this: anywhere in any chain of gets, if something goes wrong, the entire computation is stopped from that point, even if there are, oh, let's say, 1000 more valid assignments.  &lt;p&gt;  A big, and real, problem. Or 'challenge,' if you prefer.  &lt;p&gt;  Now this whole problem would go away if the Null Object pattern was used everywhere. But how to enforce that? In the Java category, you cannot. Even if you make the generic Null Object the base object, the &lt;jkey&gt;null&lt;/jkey&gt; is still Java's &amp;bottom; &amp;mdash; it's 'bottom' &amp;mdash; as low as you go in a hierarchy, &lt;jkey&gt;null&lt;/jkey&gt; is still an allowable argument everywhere.  &lt;p&gt;  And if getA(), or getB(), or getC() return &lt;jkey&gt;null&lt;/jkey&gt; you've just failed out of your entire computation with an access attempt to a null pointer.  &lt;p&gt;  &lt;h2&gt;Solutions&lt;/h2&gt;  &lt;p&gt;  &lt;h2&gt;Solution 1: test until you puke&lt;/h2&gt;  &lt;p&gt;  The first solution is to test for null at every turn. And you know what that looks like, but here you go. Because why? Because if you think it or code it, you've got to look at it, or I've got to look at it, so here it is:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt; a = getA();&lt;br /&gt;  &lt;jkey&gt;if&lt;/jkey&gt;(a != &lt;jkey&gt;null&lt;/jkey&gt;) {&lt;br /&gt;      &lt;code&gt;&lt;tt&gt;B&lt;/tt&gt;&lt;/code&gt; b = a.getB();&lt;br /&gt;      &lt;jkey&gt;if&lt;/jkey&gt;(b != &lt;jkey&gt;null&lt;/jkey&gt;) {&lt;br /&gt;          &lt;code&gt;&lt;tt&gt;C&lt;/tt&gt;&lt;/code&gt; c = b.getC();&lt;br /&gt;          &lt;jkey&gt;if&lt;/jkey&gt;(c != &lt;jkey&gt;null&lt;/jkey&gt;) {&lt;br /&gt;              foo.setD(c.getD());&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  What's the problem with this code?   &lt;p&gt;  Oh, no problems, just repeat that deep nesting for &lt;em&gt;every single assignment?&lt;/em&gt; So you have &lt;em&gt;[oh, let's say 'hypothetically']&lt;/em&gt; 2000 of these deeply nested conditional blocks?  &lt;p&gt;  And, besides the fact that it entirely clutters the simple assignment:  &lt;p&gt;  &lt;jcode&gt;foo.setD(getA().getB().getC().getD());&lt;/jcode&gt;  &lt;p&gt;  in decision logic and algorithms that are totally unnecessary and entirely too much clutter.  &lt;p&gt;  All I'm doing is assigning a &lt;code&gt;&lt;tt&gt;D&lt;/tt&gt;&lt;/code&gt; to a &lt;code&gt;&lt;tt&gt;foo&lt;/tt&gt;&lt;/code&gt;! So why do I have to juggle all this conditional code in my head to reach that eventual assignment.  &lt;p&gt;  Solution 1 is bunk.  &lt;p&gt;  &lt;h2&gt;Solution 2: narrow the catch&lt;/h2&gt;  &lt;p&gt;  &lt;p&gt;  So, solution 1 is untenable. But we need to assign where we can and skip where we can't. So how about this?  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;jkey&gt;&lt;br /&gt;  try&lt;/jkey&gt; {&lt;br /&gt;      foo.setD(getA().getB().getC().getD());&lt;br /&gt;  } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;      // Intentionally empty; silently don't assign if we cannot;&lt;br /&gt;  }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;  &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;      foo.setE(getA().getB().getC().getE());&lt;br /&gt;  } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;      // ditto&lt;br /&gt;  }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;  &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;      bar.setJ(getF().getG().getH().getJ());&lt;br /&gt;  } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;      // ditto&lt;br /&gt;  }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;  &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;      bar.setM(getF().getG().getK().getM());&lt;br /&gt;  } &lt;jkey&gt;catch&lt;/jkey&gt;(&lt;code&gt;&lt;tt&gt;Exception&lt;/tt&gt;&lt;/code&gt; ex) {&lt;br /&gt;      // ditto&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  And I say to this solution, &lt;em&gt;meh!&lt;/em&gt; Granted, it's much better than solution 1, but, again, you made a computational flow described declaratively in the problem to be these set of staccato statements, having the reader of your code switch into and out of context for every statement.  &lt;p&gt;  Wouldn't it be nice to have all the statements together in one block, because, computationally, that's what is happening: a set of data is collected from one place and moved to another, and that is what we wish to describe by keep these assignment grouped in one block.  &lt;p&gt;  &lt;h2&gt;Solution 3: Maybe Monad&lt;/h2&gt;  &lt;p&gt;  And that's what we can do with monads.  It's going to look a bit different that how you're used to the usual Java fair, as we have to lift the statements in the Java category into expressions in the monadic one.  &lt;p&gt;  So here goes.  &lt;p&gt;  First of all, we need to define generic &lt;em&gt;functions (not&lt;/em&gt; methods!&lt;a name='mark5'&gt;[&lt;/a&gt;&lt;a href='#endnote5'&gt;5&lt;/a&gt;]) for getting values from objects and setting values into object in the monadic domain:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;jkey&gt;&lt;br /&gt;  public abstract class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;SetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Datum&lt;/tt&gt;&lt;/code&gt;&gt;&lt;br /&gt;          &lt;jkey&gt;implements&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Datum&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt;&gt;&gt; {&lt;br /&gt;      &lt;jkey&gt;protected&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;SetterM&lt;/tt&gt;&lt;/code&gt;(&lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt; r) {&lt;br /&gt;          &lt;jkey&gt;this&lt;/jkey&gt;.receiver = r;&lt;br /&gt;      }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      // a monadic set function&lt;br /&gt;      &lt;jkey&gt;public final&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt;&gt; apply(&lt;code&gt;&lt;tt&gt;Datum&lt;/tt&gt;&lt;/code&gt; d) &lt;jkey&gt;throws&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Failure&lt;/tt&gt;&lt;/code&gt; {&lt;br /&gt;          set(receiver, d);&lt;br /&gt;          &lt;jkey&gt;return&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.pure(receiver);&lt;br /&gt;      }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      // subclasses implement with the particular set method being called&lt;br /&gt;      &lt;jkey&gt;protected abstract void&lt;/jkey&gt; set(&lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt; r, &lt;code&gt;&lt;tt&gt;Datum&lt;/tt&gt;&lt;/code&gt; d);&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;private final&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Receiver&lt;/tt&gt;&lt;/code&gt; receiver;&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  This declares a generic setter, so to define &lt;code&gt;&lt;tt&gt;setD&lt;/tt&gt;&lt;/code&gt; on the &lt;code&gt;&lt;tt&gt;foo&lt;/tt&gt;&lt;/code&gt; instance, we would do the following:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;code&gt;&lt;tt&gt;SetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Foo&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;D&lt;/tt&gt;&lt;/code&gt;&gt; setterDinFoo = &lt;jkey&gt;new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;SetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Foo&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;D&lt;/tt&gt;&lt;/code&gt;&gt;(foo) {&lt;br /&gt;          &lt;jkey&gt;protected void&lt;/jkey&gt; set(&lt;code&gt;&lt;tt&gt;Foo&lt;/tt&gt;&lt;/code&gt; f, &lt;code&gt;&lt;tt&gt;D&lt;/tt&gt;&lt;/code&gt; d) {&lt;br /&gt;              f.setD(d);&lt;br /&gt;          }&lt;br /&gt;      };&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  The getter functional is similarly defined, with the returned value lifted into (or 'wrapped in,' if you prefer) the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; type:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;  &lt;jkey&gt;public abstract class&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;GetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Container&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt;&gt;&lt;br /&gt;          &lt;jkey&gt;implements&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Applicable&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Container&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt;&gt;&gt; {&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;public&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt;&gt; apply(&lt;code&gt;&lt;tt&gt;Container&lt;/tt&gt;&lt;/code&gt; c) &lt;jkey&gt;throws&lt;/jkey&gt; Failure {&lt;br /&gt;          &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt;&gt; ans = (&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt;&gt;)&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.&lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;;&lt;br /&gt;          &lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt; result = get(c); &lt;br /&gt;  &lt;p&gt;&lt;br /&gt;          // &lt;code&gt;&lt;tt&gt;c&lt;/tt&gt;&lt;/code&gt; &lt;em&gt;inside the monad&lt;/em&gt; is guaranteed to be an instance&lt;br /&gt;          // but &lt;code&gt;&lt;tt&gt;result&lt;/tt&gt;&lt;/code&gt; has NO guarantees!&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;          &lt;jkey&gt;if&lt;/jkey&gt;(result != &lt;jkey&gt;null&lt;/jkey&gt;) {&lt;br /&gt;              ans = &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;.pure(result);  &lt;br /&gt;              // and now &lt;code&gt;&lt;tt&gt;ans&lt;/tt&gt;&lt;/code&gt; &lt;em&gt;is inside the monad&lt;/em&gt; it &lt;em&gt;must&lt;/em&gt; have a value.&lt;br /&gt;              // ... even if that value is &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;&lt;br /&gt;          }&lt;br /&gt;          &lt;jkey&gt;return&lt;/jkey&gt; ans;&lt;br /&gt;      }&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      &lt;jkey&gt;protected abstract&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;Returned&lt;/tt&gt;&lt;/code&gt; get(&lt;code&gt;&lt;tt&gt;Container&lt;/tt&gt;&lt;/code&gt; c);&lt;br /&gt;  }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  With the above declaration, a getter monadic &lt;em&gt;function&lt;/em&gt; (again, &lt;em&gt;not&lt;/em&gt; method) is simply defined:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;code&gt;&lt;tt&gt;GetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;B&lt;/tt&gt;&lt;/code&gt;&gt; getterBfromA = &lt;jkey&gt;new&lt;/jkey&gt; &lt;code&gt;&lt;tt&gt;GetterM&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;B&lt;/tt&gt;&lt;/code&gt;&gt;() {&lt;br /&gt;          &lt;jkey&gt;protected B&lt;/jkey&gt; get(A a) {&lt;br /&gt;              &lt;jkey&gt;return&lt;/jkey&gt; a.getB();&lt;br /&gt;          }&lt;br /&gt;      };&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  In Haskell, the &lt;code&gt;&lt;tt&gt;bind&lt;/tt&gt;&lt;/code&gt; operator has a data-flow look to it: &lt;code&gt;&lt;tt&gt;(&gt;&gt;=)&lt;/tt&gt;&lt;/code&gt;, so writing one of the 'assignments' is as simple as flowing the data to the setter:  &lt;p&gt;  &lt;code&gt;&lt;tt&gt;getA &gt;&gt;= getB &gt;&gt;= getC &gt;&gt;= getD &gt;&gt;= setD foo&lt;/tt&gt;&lt;/code&gt;  &lt;p&gt;  But we have no operator definitions, so we must soldier on using the Java syntax:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;          getterA.apply(&lt;jkey&gt;this&lt;/jkey&gt;).bind(getterBfromA).bind(getterCfromB).bind(getterDfromC).bind(setterDinFoo);&lt;br /&gt;      } &lt;jkey&gt;catch&lt;/jkey&gt; {&lt;br /&gt;          // a superfluous catch block&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  That's one of the assignment &lt;em&gt;expressions&lt;/em&gt;.&lt;a name='mark6'&gt;[&lt;/a&gt;&lt;a href='#endnote6'&gt;6&lt;/a&gt;]   &lt;p&gt;  Let's walk through what happens with a couple of examples.  &lt;p&gt;  Let's say that A has a value of &lt;code&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/code&gt;, but B is &lt;jkey&gt;null&lt;/jkey&gt;. What happens?  &lt;p&gt;  &lt;ol&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterA&lt;/tt&gt;&lt;/code&gt; forwards &lt;code&gt;&lt;tt&gt;Just a&lt;/tt&gt;&lt;/code&gt; to &lt;code&gt;&lt;tt&gt;getterBfromA&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterBfromA&lt;/tt&gt;&lt;/code&gt; gets a &lt;jkey&gt;null&lt;/jkey&gt;, converts that into a &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; and forwards that to &lt;code&gt;&lt;tt&gt;getterCfromB&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterCfromB&lt;/tt&gt;&lt;/code&gt; forwards the &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; to &lt;code&gt;&lt;tt&gt;getterDfromC&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterDfromC&lt;/tt&gt;&lt;/code&gt; forwards the &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; to &lt;code&gt;&lt;tt&gt;setterDinFoo&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;setterDinFoo&lt;/tt&gt;&lt;/code&gt; simply returns &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;.&lt;/li&gt;  &lt;/ol&gt;  And we're done (that is: we're done doing, literally: &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt;).  &lt;p&gt;  Let's counter with an example where every value has an instance:  &lt;p&gt;  &lt;ol&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterA&lt;/tt&gt;&lt;/code&gt; forwards &lt;code&gt;&lt;tt&gt;Just a&lt;/tt&gt;&lt;/code&gt; to &lt;code&gt;&lt;tt&gt;getterBfromA&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterBfromA&lt;/tt&gt;&lt;/code&gt; gets a &lt;code&gt;&lt;tt&gt;b&lt;/tt&gt;&lt;/code&gt;, converts that into &lt;code&gt;&lt;tt&gt;Just b&lt;/tt&gt;&lt;/code&gt; and forwards that to &lt;code&gt;&lt;tt&gt;getterCfromB&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterCfromB&lt;/tt&gt;&lt;/code&gt; gets a &lt;code&gt;&lt;tt&gt;c&lt;/tt&gt;&lt;/code&gt;, converts that into &lt;code&gt;&lt;tt&gt;Just c&lt;/tt&gt;&lt;/code&gt; and forwards that to &lt;code&gt;&lt;tt&gt;getterDfromC&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;getterDfromC&lt;/tt&gt;&lt;/code&gt; gets a &lt;code&gt;&lt;tt&gt;d&lt;/tt&gt;&lt;/code&gt;, converts that into &lt;code&gt;&lt;tt&gt;Just d&lt;/tt&gt;&lt;/code&gt; and forwards that to &lt;code&gt;&lt;tt&gt;setterDinFoo&lt;/tt&gt;&lt;/code&gt;&lt;/li&gt;  &lt;li&gt;&lt;code&gt;&lt;tt&gt;setterDinFoo&lt;/tt&gt;&lt;/code&gt; gets the wrapped &lt;code&gt;&lt;tt&gt;d&lt;/tt&gt;&lt;/code&gt; and sets that value in the &lt;code&gt;&lt;tt&gt;Foo&lt;/tt&gt;&lt;/code&gt; instance.&lt;/li&gt;  &lt;/ol&gt;  &lt;p&gt;  &lt;em&gt;Voil&amp;agrave;!&lt;/em&gt;  &lt;p&gt;  The beauty of this methodology is that we can put them all into one block, and every expression will be evaluated and in a type-safe manner, too, as &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; will protect us from a null pointer access:  &lt;p&gt;  &lt;pre&gt;&lt;jcode&gt;&lt;br /&gt;      &lt;jkey&gt;try&lt;/jkey&gt; {&lt;br /&gt;          getterA.apply(this).bind(getterBfromA).bind(getterCfromB).bind(getterDfromC).bind(setterDinFoo);&lt;br /&gt;  System.out.println("Hey, I've executed the first assignment");&lt;br /&gt;  getterA.apply(this).bind(getterBfromA).bind(getterCfromB).bind(getterEfromC).bind(setterEinFoo);&lt;br /&gt;  System.out.println("...and the second...");&lt;br /&gt;  getterF.apply(this).bind(getterGfromF).bind(getterHfromG).bind(getterJfromH).bind(setterJinBar);&lt;br /&gt;  System.out.println("...and third...");&lt;br /&gt;  getterF.apply(this).bind(getterGfromF).bind(getterKfromG).bind(getterMfromK).bind(setterMinBar);&lt;br /&gt;  System.out.println("...and fourth...");&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;  // another more than 2000 of these expressions&lt;br /&gt;  System.out.println("...and we're done with every assignment we &lt;em&gt;could&lt;/em&gt; assign...");&lt;br /&gt;  &lt;p&gt;&lt;br /&gt;      } &lt;jkey&gt;catch&lt;/jkey&gt; {&lt;br /&gt;          // a superfluous catch block&lt;br /&gt;      }&lt;/jcode&gt;&lt;/pre&gt;  &lt;p&gt;  And, because the monadic &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; works it does, every assignment that can occur will, and ones that cannot will be 'skipped' (by flowing &lt;code&gt;&lt;tt&gt;NOTHING&lt;/tt&gt;&lt;/code&gt; through the rest of the computation, and the proof will be in the pudding ... on the standard output will be all the statements printed.  &lt;p&gt;  &lt;h2&gt;Summary&lt;/h2&gt;  &lt;p&gt;  We presented an implementation of monads in Java, with a concrete example of the &lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt; type: the &lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt; type.  We then showed that by putting a computational set into the monadic domain, the work can be performed in a type-safe manner, even with the possible presence of &lt;jkey&gt;nulls.&lt;/jkey&gt; This is just one example of practical application of monadic programming in Java: the framework presented here confers the benefits of research of monadic programming in general to projects done in Java. Use the framework to discover for yourself the leverage monadic programming gives.  &lt;p&gt;  &lt;hr&gt;  &lt;h2&gt;End notes&lt;/h2&gt;  &lt;table border="0"&gt;   &lt;tr&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote1'&gt;[&lt;/a&gt;&lt;a href='#mark1'&gt;1&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;Exact verbage:Phil says:January 14, 2009 at 7:01 pmI think that this could all be easily cleared up if one of you FP guys would just show us how to write one of these monad thingies in JavaâTo which a semi-mocking response was: 'you know, objects would be a lot easier for me to understand if you provided an implementation in Haskell.'Exact verbage:Cory says:April 23, 2009 at 6:26 amI may be a bit late to the game here, but Phil, that can be rephrased:I think that this could all be easily cleared up if one of you OO guys would just show us how to write one of these object thingies in HaskellâOf course you can, but it's a different type of abstraction for a different way of thinking about programmingâI write 'semi-mocking,' because: 1. OOP with message passing &lt;em&gt;has&lt;/em&gt; been implemented in a Haskell-like language: Common Lisp. &lt;em&gt;The Art of the Metaobject Protocol,&lt;/em&gt; a wonderful book, covers the 'traditional' object-oriented programming methodology, and its implementation, quite thoroughly and simply.    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote2'&gt;[&lt;/a&gt;&lt;a href='#mark2'&gt;2&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;I leave it as an exercise to the reader to scope the Java category (Consult the &amp;Omega;-calculus papers, Cardelli, &lt;em&gt;et al;&lt;/em&gt;).    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote3'&gt;[&lt;/a&gt;&lt;a href='#mark3'&gt;3&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;&lt;jcode&gt;&lt;code&gt;&lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;, &lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;&lt;/jcode&gt; and &lt;jcode&gt;&lt;code&gt;&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/code&gt;&amp;lt;&lt;code&gt;&lt;tt&gt;A&lt;/tt&gt;&lt;/code&gt;&gt;&lt;/jcode&gt; are type-equivalent (but try telling the poor Java 1.6 compiler that).    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote4'&gt;[&lt;/a&gt;&lt;a href='#mark4'&gt;4&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;"The same solution &lt;em&gt;applies!"&lt;/em&gt; Geddit? Haskell is an &lt;em&gt;applicative&lt;/em&gt; language, so the same solution &lt;em&gt;applies! GEDDIT?&lt;/em&gt;    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote5'&gt;[&lt;/a&gt;&lt;a href='#mark5'&gt;5&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;The distinction I raise here between methods and functions is the following: a &lt;em&gt;method&lt;/em&gt; is enclosed in and owned by the defining class. A &lt;em&gt;function&lt;/em&gt;, on the other hand, is a free-standing object and not necessarily contained in nor attached to an object.    &lt;/td&gt;   &lt;/tr&gt;   &lt;tr&gt;    &lt;td valign='top'&gt;&lt;a name='endnote6'&gt;[&lt;/a&gt;&lt;a href='#mark6'&gt;6&lt;/a&gt;]&lt;/td&gt;    &lt;td&gt;Again, there is a distinction between an expression and a statement. An expression returns a value; a statement does not. A statement is purely imperative ... 'do something.' On the other hand, an expression &lt;em&gt;can&lt;/em&gt; be purely functional ... 'do'ing nothing, as it were, e.g.: &lt;code&gt;&lt;tt&gt;3 + 4&lt;/tt&gt;&lt;/code&gt;.  A pure expression has provable properties that can be attached to it, whereas it is extremely difficult to make assertions about statements in the general sense.  The upshot is that having pure (non-side-effecting) expressions in code allows us to reason about that code from a firm theoretical foundational basis. Such code is easier to test and to maintain. Side-effecting statement code make reasoning, testing and maintaining such code rather difficult.    &lt;/td&gt;   &lt;/tr&gt;  &lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-7366069983773698727?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/7366069983773698727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=7366069983773698727' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7366069983773698727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7366069983773698727'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2011/09/monads-in-java.html' title='Monads in Java'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-4293541267729041891</id><published>2011-04-14T12:47:00.000-07:00</published><updated>2011-04-20T03:59:37.644-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unification'/><category scheme='http://www.blogger.com/atom/ns#' term='nondeterminism'/><category scheme='http://www.blogger.com/atom/ns#' term='on-the-job'/><title type='text'>Attributed Variables: their uses and one implementation</title><content type='html'>Here's a problem that comes up enough, computationally: find a value within some range. You don't know what the value is at the moment, but you will know it, eventually, as the range becomes further restricted by refinements of the constraints or data.&lt;br /&gt;&lt;br /&gt;Now, in general, this is an easy problem for Haskell to solve, and Haskell provides more than one way to approach the solution. For example, if we have some &lt;em&gt;x&lt;/em&gt; in some domain &lt;em&gt;D,&lt;/em&gt; one way to look at an arbitrary &lt;em&gt;x&lt;/em&gt; until we find the one, true &lt;em&gt;x&lt;/em&gt; we are looking for is the following code snippet:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; [ x | x &lt;- D, ... &lt;em&gt;further constraints&lt;/em&gt; ]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;More variables? Interrelated ones? No problem:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; [ (x, y, z) | x &lt;- D, y &lt;- D, z &lt;- D, x &lt; y, ... &lt;em&gt;further constraints&lt;/em&gt; ]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Okay, let’s take it to the next level. What if the interrelation is such that one variable consumes from the domain, so that value is now unavailable to other variables. Pithily: the variables’ values are mutually exclusive.&lt;br /&gt;&lt;br /&gt;Well, one way to go about that is to embed a guard for each variable into the list compression:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; [ (x, y, z) | x &lt;- D, y &lt;- D, y /= x, z &lt;- D, z `notElem` [x,y], ...&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The drawback here is that this kind of guarded coding becomes tedious and prone to errors. On top of that we see that the guard follows the select, causing unnecessary backtracking through the search space,[1] especially given that we know the guarded values &lt;em&gt;a priori.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Well, then, we can automate guarded selection with a state (transformer) monad:[2]&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; ...&lt;br /&gt;&gt; f = do x &lt;- choose&lt;br /&gt;&gt;        y &lt;- choose&lt;br /&gt;&gt;        z &lt;- choose&lt;br /&gt;&gt; ...&lt;br /&gt;&gt; runStateT f [0..9]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Okay, excellent! All of this works and works well … for a fixed and predetermined variable set.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Problem&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Things start to get tricky for me, programmatically, however, when one set of constrained values spill over onto another set of constrained values, such as the results of one generation in a cellular automata set or genetic (algorithm) pool affect the next set:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; evalStateT (gen row1guards) domain &gt;&gt;= \ans1 -&gt;&lt;br /&gt;&gt;   evalStateT (gen (row2guards ans1)) domain &gt;&gt;= \ans2 -&gt;&lt;br /&gt;&gt;     evalStateT (gen (row3guards ans1 ans2)) domain &gt;&gt;= \ans3 -&gt;&lt;br /&gt;&gt; ... etc&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The state transformer isn’t enough, so it needs to be some RWS monad, perhaps pushing the interim results into the Reader monad and the accumulated ones into Writer while the State monad handles the flow of the computation?&lt;br /&gt;&lt;br /&gt;It seems to me that the work becomes more about monad management and less about the computation itself.[3]&lt;br /&gt;&lt;br /&gt;Then there’s the even more general computation. What if we do not know, &lt;em&gt;a priori,&lt;/em&gt; how many values we are generating in our problem solving? The problem space I’m looking at is something like:&lt;br /&gt;&lt;blockquote&gt;For a variable number of variables, map selection and guards for each variable.&lt;/blockquote&gt;&lt;br /&gt;How do I write that as a list compression expression, or as a monadic one? The problem with Haskell variables is that they aren't (variables), and so something so easily accomplished in a Prolog program:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;kakuro([], Vars, Functor) :-&lt;br /&gt;    Fn =.. [Functor, Vars],&lt;br /&gt;    call(Fn).&lt;br /&gt;kakuro([H|T], Acc, Functor) :-&lt;br /&gt;    assign(H),&lt;br /&gt;    kakuro(T, [H|Acc], Functor).&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;called with:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;?- kakuro([A, B, C, D], [], sum_equals_10).&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;or:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;?- kakuro([X, Y, Z], [], sum_equals_10).&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;... or with a list of any other length isn't so easily written out in Haskell when I go to attack the problem.  After all, what is the type of a list of unbound variables? Haskell doesn't (so easily) allow this, and I was stuck: I didn't know how to proceed using monadic programming or list compression.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;A solution&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Fortunately for me, I've been studying constraint-based programming, and that research has let me to some papers on attributed variables[4] which faciliate that programming style.&lt;br /&gt;&lt;br /&gt;Attributed variables are variables ranging over a domain that can have attributes attached to them that restrict (or constrict) the range of values. It's a very simple step to go from a set of unbound attributed variables to a (simple or fa&amp;ccedil;ile) constraint solver by adding (constraining) attributes to the variables.&lt;br /&gt;&lt;br /&gt;More formally, I declare (denotationally) an attributed variable as:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; data &lt;tt&gt;Attribute&lt;/tt&gt; a = &lt;tt&gt;Attribute&lt;/tt&gt; [&lt;tt&gt;Constraint&lt;/tt&gt; a] (&lt;tt&gt;Domain&lt;/tt&gt; a)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;where &lt;tt&gt;Constraint&lt;/tt&gt; and &lt;tt&gt;Domain&lt;/tt&gt; are declared as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; newtype &lt;tt&gt;Constraint&lt;/tt&gt; a = &lt;tt&gt;Constraint&lt;/tt&gt; { resolve :: a -&gt; &lt;tt&gt;Bool&lt;/tt&gt; }&lt;br /&gt;&lt;br /&gt;&gt; type &lt;tt&gt;Domain&lt;/tt&gt; a = [a]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Or, to put words to it, an Attributed Variable is an object that has a set of (constraining) functions over an assigned domain.[5]&lt;br /&gt;&lt;br /&gt;The above denotational declaration of attributed variables works, but I find, operationally, grounding an attributed variable once it's reduced to a single value to be useful:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; data Attribute a = Attribute [Constraint a] (Domain a)&lt;br /&gt;&gt;     | Ground a&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, that's my declaration.[8] How is this implemented in practice?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Implementation&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The approach I take is that an attributed variable is created in a free state over its domain:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; makeAttrib :: &lt;tt&gt;Domain&lt;/tt&gt; a -&gt; &lt;tt&gt;Attribute&lt;/tt&gt; a&lt;br /&gt;&gt; makeAttrib list = &lt;tt&gt;Attribute&lt;/tt&gt; [] list&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And then, as constraints are added to the attributed variable, the system 'tries to solve' the attributed variable over the set of the constraints:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; constrain (&lt;tt&gt;Attribute&lt;/tt&gt; constraints dataset) constraint&lt;br /&gt;&gt;    = solve (&lt;tt&gt;Attribute&lt;/tt&gt; (&lt;tt&gt;Constraint&lt;/tt&gt; constraint:constraints) dataset)&lt;br /&gt;&gt; constrain (&lt;tt&gt;Ground&lt;/tt&gt; x) _ = &lt;tt&gt;Ground&lt;/tt&gt; x&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And if the solution results in a singleton list, then the attributed variable becomes &lt;tt&gt;Ground&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; solve attr@(&lt;tt&gt;Attribute&lt;/tt&gt; _ []) = attr&lt;br /&gt;&gt; solve attr@(&lt;tt&gt;Attribute&lt;/tt&gt; constraints list@(h:t))&lt;br /&gt;&gt;    = let result = solve' constraints list&lt;br /&gt;&gt;      in if length result == 1&lt;br /&gt;&gt;         then &lt;tt&gt;Ground&lt;/tt&gt; (head result)&lt;br /&gt;&gt;         else &lt;tt&gt;Attribute&lt;/tt&gt; constraints result&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, the 'solution' to a &lt;tt&gt;Ground&lt;/tt&gt; attributed variable is itself:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; solve (Ground x) = Ground x&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The above code is simply a dispatch along the binary type. The worker-bee, &lt;code&gt;solve'&lt;/code&gt; is simply (again) an implementation of the dual of &lt;code&gt;filter&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; solve' :: [&lt;tt&gt;Constraint&lt;/tt&gt; a] -&gt; [a] -&gt; [a]&lt;br /&gt;&gt; solve' _ [] = []&lt;br /&gt;&gt; solve' constraints (h:t) =&lt;br /&gt;&gt;    if   (solveConstraints constraints h)&lt;br /&gt;&gt;    then (h:solve' constraints t)&lt;br /&gt;&gt;    else solve' constraints t&lt;br /&gt;&lt;br /&gt;&gt; solveConstraints :: [&lt;tt&gt;Constraint&lt;/tt&gt; a] -&gt; a -&gt; &lt;tt&gt;Bool&lt;/tt&gt;&lt;br /&gt;&gt; solveConstraints [] _ = &lt;tt&gt;True&lt;/tt&gt;&lt;br /&gt;&gt; solveConstraints (f:rest) x = resolve f x &amp;&amp; solveConstraints rest x&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So something from &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Applicative&lt;/tt&gt; to reduce that to a one-liner? I leave that as an exercise to the reader.&lt;br /&gt;&lt;br /&gt;And there you have it, that is a working implementation of attributed variables. I have test functions for groundedness, solvability and the current state of the domain of an active attributed variable, but those are simple helper functions, easily implemented, and provided in the attached source code.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Uses&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;So, now, what do we have?&lt;br /&gt;&lt;br /&gt;Now we have variables over which we may specify a domain ('loosely' typing a variable) and then constrain. How can we use such a system?&lt;br /&gt;&lt;br /&gt;One way is that we can write constraint logic programs in Haskell. The illustration from Prolog (above) has a nearly direct transliteration into Haskell (with the additional benefit of strong typing):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; kakuro :: [&lt;tt&gt;Int&lt;/tt&gt;] -&gt; &lt;tt&gt;Int&lt;/tt&gt; -&gt; [[&lt;tt&gt;Int&lt;/tt&gt;]]&lt;br /&gt;&gt; kakuro list total = nub $ summer (sort $ map trib list) [] total&lt;br /&gt;&lt;br /&gt;&gt; trib :: &lt;tt&gt;Int&lt;/tt&gt; -&gt; &lt;tt&gt;Attribute Int&lt;/tt&gt;&lt;br /&gt;&gt; trib x | x == 0    = makeAttrib [1..9]&lt;br /&gt;&gt;        | otherwise = &lt;tt&gt;Ground&lt;/tt&gt; x&lt;br /&gt;&lt;br /&gt;&gt; summer :: [&lt;tt&gt;Attribute Int&lt;/tt&gt;] -&gt; [&lt;tt&gt;Int&lt;/tt&gt;] -&gt; &lt;tt&gt;Int&lt;/tt&gt; -&gt; [[&lt;tt&gt;Int&lt;/tt&gt;]]&lt;br /&gt;&gt; summer [] list total = do&lt;br /&gt;&gt;    guard $ sum list == total&lt;br /&gt;&gt;    return $ sort list&lt;br /&gt;&gt; summer (h:t) list total = do&lt;br /&gt;&gt;     a &lt;- domain $ constrain h (flip notElem list)&lt;br /&gt;&gt;     summer t (a:list) total&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And with the above code, we can now do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;*Kakuro&gt; kakuro [0,0,0] 10&lt;br /&gt;[[1,2,7],[1,3,6],[1,4,5],[2,3,5]]&lt;br /&gt;*Kakuro&gt; kakuro [0,0,0,0] 10&lt;br /&gt;[[1,2,3,4]]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that I use &lt;code&gt;sort&lt;/code&gt; above, but attributed variables are not (denotationally) ordered types. Operationally, that is: in logical programming, it makes sense to eliminate early, so if we have &lt;tt&gt;Ground&lt;/tt&gt; values, we wish to consume those first. So, to that end, I declare the following instances:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; instance (&lt;tt&gt;Eq&lt;/tt&gt; a) =&gt; &lt;tt&gt;Eq&lt;/tt&gt; (&lt;tt&gt;Attribute&lt;/tt&gt; a) where&lt;br /&gt;&gt;     &lt;tt&gt;Ground&lt;/tt&gt; x == &lt;tt&gt;Ground&lt;/tt&gt; y = x == y&lt;br /&gt;&gt;     _        == _        = &lt;tt&gt;False&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; instance (&lt;tt&gt;Ord&lt;/tt&gt; a) =&gt; &lt;tt&gt;Ord&lt;/tt&gt; (&lt;tt&gt;Attribute&lt;/tt&gt; a) where&lt;br /&gt;&gt;     &lt;tt&gt;Ground&lt;/tt&gt; x &lt;= &lt;tt&gt;Ground&lt;/tt&gt; y = x &lt;= y&lt;br /&gt;&gt;     &lt;tt&gt;Ground&lt;/tt&gt; _ &lt;= _        = &lt;tt&gt;True&lt;/tt&gt;&lt;br /&gt;&gt;     _        &lt;= _    = &lt;tt&gt;False&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And with those instance declarations, &lt;code&gt;sort&lt;/code&gt; &lt;a href="http://www.catb.org/jargon/html/A/automagically.html"&gt;automagically&lt;/a&gt; works. Neat!&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Interlude: Haskell is "Neat"&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;I don't know about you, but I'm guessing that many of you are taking the gift that Haskell is for granted.  Or I suppose I should say 'the way of thinking that using Haskell provides.'  Over and over again in industry (yes: &lt;a href="http://www.catb.org/jargon/html/S/stone-knives-and-bearskins.html"&gt;stone knives and bearskins&lt;/a&gt;) I hear 'that can't be done.' And I find myself puzzled. What's the &lt;a href="http://www.catb.org/jargon/html/S/showstopper.html"&gt;showstopper&lt;/a&gt; here?&lt;br /&gt;&lt;br /&gt;For example, this past week at work, we needed to convert a data mapping document in Excel (stop snickering, please) into an equivalently flat XML schema representation with a accompanying XML sample file. So fields of the form:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;root&gt;/Field/Name="BusinessAddress"&lt;br /&gt;&lt;root&gt;/Field/Value="plaintext"&lt;br /&gt;&lt;br /&gt;&lt;root&gt;/Field/Name="BusinessAddress"&lt;br /&gt;&lt;root&gt;/Field/Value="encrypted"&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And there were enumerated values as well:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;root&gt;/Field/Name="PropertyOccupancyTypeOwnerOccupied"&lt;br /&gt;&lt;root&gt;/Field/Value="plaintext"&lt;br /&gt;&lt;br /&gt;&lt;root&gt;/Field/Name="PropertyOccupancyTypeRentedToTenant"&lt;br /&gt;&lt;root&gt;/Field/Value="plaintext"&lt;br /&gt;&lt;br /&gt;&lt;root&gt;/Field/Name="PropertyOccupancyTypeVacant"&lt;br /&gt;&lt;root&gt;/Field/Value="plaintext"&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There were over 1,000 of these element names. I mentioned I would write a parser to generate the XSD and XML and was told by the development team point-blank that that was impossible and the only way to go about this transcription was manually, line-by-line, by hand.&lt;br /&gt;&lt;br /&gt;So I wrote the script. I suppose I could have used Perl, but as I'm on a Windows box, the shell isn't very inviting for Perl-like piping, so I used Haskell, stripping the metainformation and pushing the parsed names into a map (or, to be precise, a &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Map&lt;/tt&gt;) where enumerated (mutally exclusive instance) types went into a list named by their type name and other values were singletons.  Then for the XSD I simply iterated over the elements of the map (recursively), and for the sample XML file, I just chose an element (in this case, the first element) of each type.&lt;br /&gt;&lt;br /&gt;The net result was that all the elements analysis team compiled into an Excel spreadsheet by hand over a six week period I was able to deliver in two days as a full XSD schema and a comprehensive XML sample file.&lt;br /&gt;&lt;br /&gt;Two members from the development team assisted me on this task, one of them was the lead developer. He was intrigued and asked me: "What does this script do?" after being impressed that he could generate a schema definition file and a sample file in seconds.  So I explained Haskell as a 'data-flow' language and I traced the flow of the input file through the monad and function composition showing the translation of the internal representation into XSD and then, in a different context, into XML.  I'm not sure he got my explanation, but he did walk away impressed with what Haskell can do.&lt;br /&gt;&lt;br /&gt;Yes, these are simple things: parsing, mapping, iterating. But for most of the software engineering community in industry, it is easier and faster to go through, line-by-line, by hand, than to write a piece of code to automate that process ("Can that even be done?" "No, it's impossible, just do it manually").&lt;br /&gt;&lt;br /&gt;I have encountered this over and over again in industry. Teams are willing to expend more than two hundred person hours to a reoccuring task and are willing to accept the associated fatigue errors to schedule systems by hand. Then they are shocked that I build a functional or logic-based system that autogenerates a pristine result in sub-second time.&lt;br /&gt;&lt;br /&gt;Where does this leave us?&lt;br /&gt;&lt;br /&gt;What I see as status quo is that industry is resigned to slog through repetitive tasks manually, because it's too hard in Language X to consider tackling the problem: more time would be spent writing, compiling and fixing a program to do the task than to do the task by hand.&lt;br /&gt;&lt;br /&gt;On the academic side, I see researchers isolated from industry, feeling their advances have no practical use as there appears to be no interest from industry. I attended a talk on dependent types where the thesis was that this typing makes coding more declarative, more powerful and less error prone. I approached the lecturer and asked how I could implement such a system and was asked what application dependent types had for industry.&lt;br /&gt;&lt;br /&gt;Hm. Let me think on that for a while.&lt;br /&gt;&lt;br /&gt;Why would industry be interested in coding more declaratively, more powerfully, and with less errors? I was flabbergasted that the researcher saw no benefit for industry in his presentation.&lt;br /&gt;&lt;br /&gt;We have a powerful tool in Haskell. We can do more, cleaner, safer, and do it faster than the mainstream alternatives industry picks over and over again by default.&lt;br /&gt;&lt;br /&gt;I've found, however, that talking about typing, or monads, or pure functional programming only causes the eyes to glaze.&lt;br /&gt;&lt;br /&gt;What lights a fire in management's eyes? When you rescue an overdue project, delivering before the deadline, and you educate other workers to be as productive ... perhaps not writing Haskell themselves (I've been asked: "Is it like Pascal?" ... and that's &lt;em&gt;after&lt;/em&gt; a code walkthrough), but using the tools you've used to deliver these 'tremendous' results, and earning their trust that when you say, 'just let me write a Haskell script to do that: I'll take a day to write it, and we'll start getting results right away,' that that is actually what happens.  I've found that 'we should use Haskell because of [all the wonderful arguments put forward]' does not convince anybody.  Delivering 'incredible' and 'impossible' results, significantly faster than anticipated (two days instead of two months for the XML project)?  That moves mountains.&lt;br /&gt;&lt;br /&gt;Where I work, Haskell is installed on two lead developer's systems other than my own, and I'm given permission to code in Haskell, on a 'we only allow Language X' project.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Other Uses&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;So attributed variables can be used to help one solve &lt;a href="http://www.menneske.no/kakuro/eng/"&gt;kakuro&lt;/a&gt; puzzles, or to write a sudoku solver. Fine.&lt;br /&gt;&lt;br /&gt;And I've been inching my way toward attributed variables, so it can be applied to &lt;a href="http://logicaltypes.blogspot.com/2008/07/dont-know-dont-care-whatever.html"&gt;symbolic logic puzzles&lt;/a&gt; as well, replacing my &lt;tt&gt;Whatever&lt;/tt&gt; type with attributed variables over the enumerated domain.&lt;br /&gt;&lt;br /&gt;So the domain is not restricted to Number, but these are not very interesting or pragmatic examples in and of themselves. Not very gripping.&lt;br /&gt;&lt;br /&gt;So how about this example?&lt;br /&gt;&lt;br /&gt;&lt;code&gt;*Stocks&gt; makeAttribute [Buy, Sell, Hold]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;with &lt;tt&gt;Constraint&lt;/tt&gt;s being input feeds filtered through weighted moving averages and other indicators.  Now this is a system of keen interest for me and 'currently under active and intense research.'&lt;br /&gt;&lt;br /&gt;Will such a system work or not work? I'm not at liberty to say,[9] but here is an area that appears to fit well in the language space of constraint programming.&lt;br /&gt;&lt;br /&gt;As problem spaces attacked by software projects &amp;mdash; workflow analysis, data mining, planning and scheduling, budgeting, forecasting, (war)gaming, modelling and simulation &amp;mdash; many seem good candidates to use constraint-based reasoning.  Attributed variables give Haskell programmers another way to express these problem domains.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;h2&gt;Endnotes:&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;[1] Y’all don’t mind if I speak logically, and in the logic-programming paradigm, do you?&lt;br /&gt;&lt;br /&gt;[2] See my article in &lt;em&gt;The Monad.Reader,&lt;/em&gt; issue 11, “MonadPlus: What a Super Monad!” for an implementation of &lt;code&gt;choose&lt;/code&gt;, &lt;em&gt;et al.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;[3] No, I’m not speaking disparagingly of the monadic programming style. I rather like that style, and use it in my domain language of predicate logic that I layer on top of ‘regular’ Haskell programming.  The beauty of monads, for me, is that they are invisible (in coding them) and powerful (in their effect). When the code becomes more about monads and less of what they are there to do is when I see this as an opportunity to examine things in a different light.&lt;br /&gt;&lt;br /&gt;[4] http://www.swi-prolog.org/pldoc/doc_for?object=section(2,'6.1',swi('/doc/Manual/attvar.html'))&lt;br /&gt;&lt;br /&gt;[5] My representation of &lt;tt&gt;Domain&lt;/tt&gt; is straightforward and workable for most cases, but it hides more than a few compromises (or 'sell-outs') beneath the surface.  For example, it makes the (gross) assumption that the range of the domain is enumerable. If &lt;tt&gt;Domain&lt;/tt&gt; is in &amp;real; that no longer holds (at all), so then &lt;tt&gt;Domain&lt;/tt&gt; &lt;em&gt;shouldn't&lt;/em&gt; have a list representation but a pair (or bookending) bounds.  But then what if &lt;tt&gt;Domain&lt;/tt&gt; extends beyond &amp;real; and goes into the &lt;em&gt;surreal&lt;/em&gt; numbers?[6] Then we have infintesimals such as '*' (&lt;em&gt;pron:&lt;/em&gt; 'star') where:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;* &gt; 0, * &lt; 0, * + * = 0&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;and:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;* || 0&lt;/code&gt; (that is: 'star' &lt;em&gt;is incomparable to&lt;/em&gt; 0)&lt;br /&gt;&lt;br /&gt;So how does one bounds-check on incomparables?&lt;br /&gt;&lt;br /&gt;But these concerns are, in the main, not ones to lose one's head over. For the most part, simple linear programming solves a vast majority of the World's problems,[7] and those interesting cases are exactly that: interesting cases.&lt;br /&gt;&lt;br /&gt;[6] http://en.wikipedia.org/wiki/Surreal_number&lt;br /&gt;&lt;br /&gt;[7] The preface of &lt;em&gt;How to Solve It: Modern Heuristics&lt;/em&gt; by Zbigniew Michalewicz and David B. Fogel makes this assertion, from hard-won experience in the field. Seconded.&lt;br /&gt;&lt;br /&gt;[8] This is one approach to attributed variables, that is: constraints or attributes are applied to the variable over the domain until it is reduced to a single value, at which point the constraints and even the domain become superfluous and simply go away. An advantage to this approach is that a test for groundedness becomes trivial. A disadvantage is that once grounded one loses the path or information that got one there except through the data flow through the algorithm (the stack trace, as it were).  Another disadvantage is that an attributed variable, once grounded, automatically rejects constraints. This may lead to unexpected program behavior, because AV grounded to 5 with a new constraint of &lt;code&gt;x &gt; 23&lt;/code&gt; should fail, but my implementation forwards the 5 value in a success state.&lt;br /&gt;&lt;br /&gt;[9] An audit trail of at least a year of data is necessary before any claims can be made.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-4293541267729041891?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/4293541267729041891/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=4293541267729041891' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4293541267729041891'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4293541267729041891'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2011/04/attributed-variables-their-uses-and-one.html' title='Attributed Variables: their uses and one implementation'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1416240855056065142</id><published>2010-09-14T08:35:00.000-07:00</published><updated>2010-09-28T16:03:18.067-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='difference lists'/><category scheme='http://www.blogger.com/atom/ns#' term='combinatory logic'/><category scheme='http://www.blogger.com/atom/ns#' term='reading list'/><title type='text'>'List' leads off with the letter 'Lambda' (λ)</title><content type='html'>I was revisiting the &lt;a href="http://projecteuler.net/"&gt;Project Euler&lt;/a&gt; problems recently, and one of the problems addressed lexicographic permutations.&lt;br /&gt;&lt;br /&gt;Well, problem solved if you're using C++ or other languages that have lexicographic_permutation packaged with their standard library set.  Some languages do and some don't, but that discussion is not &lt;em&gt;&amp;agrave; propos&lt;/em&gt; to this article, nor even what lexicographic permutations are or how to go about getting to them.&lt;sup&gt;&lt;small&gt;&lt;a href='#fn-look-endnotes1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;But something common enough did come up in the solving of that problem, which is the question of appending to the end of lists effectively.&lt;br /&gt;&lt;br /&gt;Now, I have a prejudice: I love lists, and by that I mean to say is that in more than a few functional and logical programming languages, the List Data Structure (uttered with reverence, and with not even (barely) a hint of mocking) provides a facility for grouping and then operating on sets of objects that I find unparalleled in other programming languages and paradigms.  I can, for example, in &lt;a href='http://haskell.org'&gt;Haskell&lt;/a&gt; create a list simply by typing &lt;code&gt;[0..9]&lt;/code&gt; or &lt;code&gt;["Mary", "Sue", "Bob"]&lt;/code&gt;, and if I'm feeling old-fashioned and gutsy, I can iterate through those lists inductively with a:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;doSomething [] = []&lt;br /&gt;doSomething (h:t) = f h : doSomething t&lt;/pre&gt;&lt;br /&gt;Or if I wish to embrace the modern era of programming (like, oh, since the 1970ish-es),&lt;sup&gt;&lt;small&gt;&lt;a href='#fn-look-endnotes2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; I can use &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;fold&lt;/code&gt; to go anywhere I want to with a list.  I mean, come on! &lt;code&gt;fold&lt;/code&gt; is, after all, the 'program transformer function.' If I don't like my list as it is now (or if I don't even like it being a list at all), I just &lt;code&gt;fold&lt;/code&gt; over it until it's exactly how I want it to be.&lt;br /&gt;&lt;br /&gt;Like the above function, it's really just a specialization of &lt;code&gt;map&lt;/code&gt;, isn't it?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;map _ [] = []&lt;br /&gt;map f (h:t) = f h : map f t&lt;/pre&gt;&lt;br /&gt;And &lt;code&gt;map&lt;/code&gt; is just a specialization of &lt;code&gt;fold&lt;/code&gt;, right?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;foldr ((:) . f) [] &amp;equiv; map f&lt;/pre&gt;&lt;br /&gt;So, yeah, lists rock my world.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;But,&lt;/em&gt; you complain, &lt;em&gt;I know language X&lt;/em&gt; [yes, the great language (flame-)war, with endless debates in the imperial senate, continues] &lt;em&gt;and language X has lists and &lt;code&gt;map&lt;/code&gt;, so what's the big deal?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The big deal is this: have you ever tried to construct a list in language X? Is it easy as the example I provided above?&lt;br /&gt;&lt;br /&gt;&lt;em&gt;No, but ...&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Yeah, no, it's not as easy.  In fact, I've done quite a bit of programming in language X, and I put forward that constructing and then destructuring lists is a painfully long and tedious process:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;BidirectionalLinkedList&lt;String&gt; list = new BidirectionalLinkedList&lt;String&gt;();&lt;br /&gt;list.add("Mary");&lt;br /&gt;list.add("Sue");&lt;br /&gt;list.add("Bob");&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Blech!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;BUT THEN it gets better when you do destructuring:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;BidirectionalLinkedList&lt;String&gt; newlist = new BidirectionalLinkedList&lt;String&gt;();&lt;br /&gt;for(String elem : list) { newlist.add(doit(elem)); }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Um, and that's &lt;em&gt;only after&lt;/em&gt; the "stunning" advances that the STL started with functionals&lt;sup&gt;&lt;small&gt;&lt;a href='#fn-look-endnotes3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; grafted onto the language, so have you seen the contortions you have to go through to create a functional object to map with? And don't you dare get your template parameter off because the compiler error...? &lt;em&gt;shudder!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Enough of that.&lt;br /&gt;&lt;br /&gt;So lists are structures or collections, and structures can be viewed as objects (phenomenon), and that is a very useful and powerful way to view them and to define them:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;data List t = [] | (t : List t)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No problem with that and everything is right with the world.&lt;br /&gt;&lt;br /&gt;... until it isn't.&lt;br /&gt;&lt;br /&gt;This definitely works, and works well, for lists in general, and it also works great most of the time for working with the elements of the list.  After all, in practice, we are most concerned with the element we have worked on most recently, so, in most cases, the element we just put in is the element we'd most likely to be retrieving ... &lt;em&gt;AND&lt;/em&gt; (generally) our interest diminishes the further (in time) we are from an element, and that translates directly into where elements are found in a list.&lt;br /&gt;&lt;br /&gt;Generally.&lt;br /&gt;&lt;br /&gt;So, in general, lists work just fine; great, in fact.&lt;br /&gt;&lt;br /&gt;There are specific cases where what we care about is not the most recent element, but another ordering is important.  Two cases spring immediately to mind: first, queuing, and secondly (and commonly and specifically), document assembly.&lt;br /&gt;&lt;br /&gt;In these two cases we wish to push onto the end of the list new elements, and the above definition doesn't give us access to the &lt;em&gt;last&lt;/em&gt; element or position of the list.  And to get that access, we must reverse the list so the last element becomes the first, or prepend to a reversed list.  Either of these options has at least a cost in linear time when &lt;code&gt;reverse&lt;/code&gt; is (eventually) called.&lt;br /&gt;&lt;br /&gt;Or, we must call &lt;code&gt;append&lt;/code&gt; or a function like it to append elements to the end of the working list; this also has linear costs.  Either way, we pay the full price.&lt;br /&gt;&lt;br /&gt;Now there are objects that do give us immediate access to that last element and position: deques and queues, for example, but when we go there, we give up the ease of composition and decomposition that we have with lists.  We pay a penalty in expressitively with these types or in performance when using lists against their nature.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Or do we?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Well, one way of looking at lists is as objects, and above we gave a definition of lists as objects, but this is not the only way to view lists.  I propose another way of looking at lists: lists can be viewed as functions.&lt;sup&gt;&lt;small&gt;&lt;a href='#fn-list-endnotes4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(:) :: t &amp;rarr; [t] &amp;rarr; [t]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above definition says that &lt;code&gt;(:)&lt;/code&gt; &lt;em&gt;(pronounced 'cons')&lt;/em&gt; takes an element and a list and gives a list.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Yeah, so?&lt;/em&gt; you ask, for this is already a well-known function in the list lexicon.&lt;br /&gt;&lt;br /&gt;I propose we look at this function in an entirely different way:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(:) :: t &amp;rarr; ([t] &amp;rarr; [t])&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this case, &lt;code&gt;(:)&lt;/code&gt; constructs a list &lt;em&gt;function&lt;/em&gt; from a seed element. This allows us to use this function a novel but perfectly acceptable way:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;x |&gt; list = (x:) . list&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What we are saying here is that &lt;code&gt;(|&gt;)&lt;/code&gt; &lt;em&gt;(pronounced 'put to front')&lt;/em&gt; is an operator that takes an &lt;code&gt;x&lt;/code&gt; and puts that value on the front of &lt;code&gt;list&lt;/code&gt;, just like &lt;code&gt;(:)&lt;/code&gt; does.&lt;br /&gt;&lt;br /&gt;The difference here &lt;em&gt;(heh:&lt;/em&gt; 'difference') (sorry, mathematician humor) is what &lt;code&gt;list&lt;/code&gt; is.  For &lt;code&gt;(:)&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt; is of type &lt;tt&gt;[a]&lt;/tt&gt; (or, directly and tautologically: &lt;code&gt;list&lt;/code&gt; is a list), but for &lt;code&gt;(|&gt;)&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt; is of type &lt;tt&gt;[a] &amp;rarr; [a]&lt;/tt&gt;.  Or, translating: &lt;code&gt;list&lt;/code&gt; is a &lt;em&gt;function.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;So? You've just reinvented the wheel with lists as functions now. Big deal.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Well, actually, what I've done is to reinvent the wheel as a meta-wheel, and so the big deal is this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;list &amp;lt;| x = list . (x:)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What we have here with &lt;code&gt;(&amp;lt;|)&lt;/code&gt; &lt;em&gt;(pronounced 'put to back')&lt;/em&gt; is a function that adds an element to the end of a list in &amp;mdash; &lt;em&gt;wait for it!&lt;/em&gt; &amp;mdash; &lt;em&gt;constant time&lt;/em&gt;.  For 'regular' lists the best you can do that operation is in linear time, and so my work of constructing a document by appending to the end of a list that was occurring in O(n&amp;sup2;) time has just gone to a linear-time operation.  Not a big deal for a small document, but we found that once a document became more than a page or two, the operation went from 'a blink of an eye' to 'keeping your eyes closed until the cows came home ... that had been eaten by wolves.' This is not the case with lists as functions: document construction became reasonable endeavor (that is, it occurred so quickly for us mere humans, living in this non-nanosecond-time, we didn't notice the elapsed time).&lt;br /&gt;&lt;br /&gt;So, I've been a sly thing in one respect. I still haven't told you what a (functional) list is. I've defined the object view of lists, and I've &lt;em&gt;declared&lt;/em&gt; what a function view of lists, but haven't defined them.&lt;br /&gt;&lt;br /&gt;Here.  Allow me to define them now:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;empty = id&lt;/pre&gt;&lt;br /&gt;There you go. There are the 'definitions.' I say 'definition&lt;em&gt;s&lt;/em&gt;' because with that sole definition, everything works, for to ground a functional list, we simply pass it an empty list:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;empty [] ⇒ []&lt;/pre&gt;&lt;br /&gt;Or even whatever list we are working with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;empty [1,2,3] ⇒ [1,2,3]&lt;/pre&gt;&lt;br /&gt;When you append something to an empty list, you get that something back.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;AND&lt;/em&gt; &lt;code&gt;empty&lt;/code&gt; works as the seed of the 'put to' operators:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(5 |&gt; 6 |&gt; 2 |&gt; empty) [1,2,4] ⇒ [5,6,2,1,2,4]&lt;/pre&gt;&lt;br /&gt;and:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;(empty &amp;lt;| 1 &amp;lt;| 2 &amp;lt;| 3) [4,5,6] ⇒ [1,2,3,4,5,6]&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It all works!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;In this article we've demonstrated that there's more than one way to look at, specifically, lists. The standard way is to view them is as objects, and for the most cases, that works, and works well: this view provides a syntax that makes list processing simple and intuitive.&lt;br /&gt;&lt;br /&gt;We've also shown that that is not the sole way to view things, and this view can be constraining, particularly when lists are played against type as a queue or a document assembler.  In these cases it becomes simpler, declaratively, to view lists as functions, and not only does that provide a syntax for simple list construction either at the beginning or the end of the list, but also provide constant-time construction at either end.  Furthermore, defining this view is as simple as viewing the empty list as &lt;code&gt;id&lt;/code&gt; and then using the partial function of &lt;code&gt;(:)&lt;/code&gt; &lt;em&gt;('cons')&lt;/em&gt;. That's the generative view. Then, to extract the ("real") list from that view, it's as simple as sending a list (for example, &lt;code&gt;[]&lt;/code&gt;) to that functional list to ground the value for disposition.&lt;br /&gt;&lt;br /&gt;In these special cases of working at the back end of a list, that aren't all that rare, the functional view of list processing gives the programmer expressivity and efficiency, eliminating the chore of appending to the end or reversing the target list. I quite enjoy list processing this way: it gives me a fresh perspective on an old friend and makes list processing in these cases easy and fun.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Endnotes&lt;/strong&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tr&gt;&lt;td valign='top'&gt;&lt;p&gt;&lt;small&gt;&lt;sup&gt;&lt;a name='fn-look-endnotes1'&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/small&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;There is an article at &lt;a href='http://wordaligned.org/articles/next-permutation'&gt;http://wordaligned.org/articles/next-permutation&lt;/a&gt; that provides a simple, clear explanation of the lexicographic permutation algorithm with a very nice demonstrative example if you are so inclined to investigate.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td valign='top'&gt;&lt;p&gt;&lt;small&gt;&lt;sup&gt;&lt;a name='fn-look-endnotes2'&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/small&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Laurent Sikl&amp;oacute;ssy, &lt;em&gt;&lt;a href="http://www.amazon.com/Lets-Talk-LISP-Laurent-Siklossy/dp/0135327628"&gt;Let's Talk Lisp&lt;/a&gt;&lt;/em&gt; talks about &lt;tt&gt;MAPCAR&lt;/tt&gt; in chapter 6.  And, if I may: this book is one of the rare ones. It's one of those books like Smullyan's &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/To_Mock_a_Mockingbird"&gt;To Mock a Mockingbird&lt;/a&gt;&lt;/em&gt; or van der Linden's &lt;em&gt;&lt;a href="http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298"&gt;Deep C Secrets&lt;/a&gt;&lt;/em&gt; (with a &lt;em&gt;fish&lt;/em&gt; on the orange book cover, no less!) or, and let us not forget the ultimate: Hofstadter's &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach"&gt;G&amp;ouml;del, Escher and Bach: the Eternal Golden Braid&lt;/a&gt;&lt;/em&gt; (I mean, even the &lt;em&gt;title&lt;/em&gt; is a pun, Doug doesn't waste time in having fun, does he? He gets right to it!) that make you a better person but you don't notice it, but everybody else does, because you are constantly busting out laughing or grinning from ear-to-ear at the cleverness of their prose. Why do books about esoterica have to be so &lt;em&gt;heavy!&lt;/em&gt;  These esoteric books show that they don't have to be heavy in the lightness they deal with the subject (and deal with &lt;em&gt;dealing with&lt;/em&gt; these esoteric subjects).&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And who is that bright young man who left such a feisty review of that book back in &lt;em&gt;(*le gasp!*)&lt;/em&gt; 2001? I can see a promising future for that boy, just so long as he doesn't get too big for his britches.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&amp;Agrave; propose de rien,&lt;/em&gt; what are britches?&lt;br /&gt;&lt;br /&gt;&lt;p&gt;*ahem* Yes, so those books are three of my favorites ... which ones are yours?&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td valign='top'&gt;&lt;p&gt;&lt;sup&gt;&lt;small&gt;&lt;a name='fn-look-endnotes3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Bjarne Stroustrup, &lt;em&gt;&lt;a href="http://www2.research.att.com/~bs/3rd.html"&gt;The C++ Programming Language, 3rd ed.&lt;/a&gt;&lt;/em&gt;, &amp;sect;18.4&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td valign='top'&gt;&lt;p&gt;&lt;sup&gt;&lt;small&gt;&lt;a name='fn-look-endnotes4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Such a view of lists has a name: these functional list types are called &lt;em&gt;&lt;a href="http://logicaltypes.blogspot.com/search/label/difference%20lists"&gt;difference lists&lt;/a&gt;&lt;/em&gt; from the Prolog community.  The &lt;a href="http://www.haskell.org/ghc/docs/6.12.2/html/libraries/index.html"&gt;standard Haskell library&lt;/a&gt; does &lt;em&gt;not&lt;/em&gt; have &lt;tt&gt;&lt;a href="http://hackage.haskell.org/packages/archive/dlist/0.5/doc/html/Data-DList.html"&gt;Data.DList&lt;/a&gt;&lt;/tt&gt; &lt;em&gt;[sad loss, I say!]&lt;/em&gt; but this type is provided by Don Stewart of &lt;a href="http://www.galois.com/"&gt;Galois&lt;/a&gt; in the &lt;a href="http://hackage.haskell.org/packages/hackage.html"&gt;hackageDB&lt;/a&gt; under the &lt;a href="http://hackage.haskell.org/cgi-bin/hackage-scripts/package/dlist"&gt;dlist&lt;/a&gt; package.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The &lt;tt&gt;Data.DList&lt;/tt&gt; works great, but I've implemented my own system that is more than twice as fast as I provide several specialized implementations of difference list operators that take a more direct approach in their implementations (&lt;code&gt;foldr&lt;/code&gt; is elegant but can be a costly operation). If you'd like to use my &lt;tt&gt;Data.DiffList&lt;/tt&gt; package please contact me, and I'll be delighted to share this library.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1416240855056065142?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1416240855056065142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1416240855056065142' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1416240855056065142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1416240855056065142'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2010/09/list-leads-off-with-letter-lambda.html' title='&apos;List&apos; leads off with the letter &apos;Lambda&apos; (λ)'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-8339634600444486934</id><published>2010-05-26T07:24:00.000-07:00</published><updated>2010-05-27T07:09:37.810-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='the &apos;real world&apos;'/><category scheme='http://www.blogger.com/atom/ns#' term='pensées'/><title type='text'>Math is hard</title><content type='html'>So, here's an interesting, everyday conundrum, sent to me by a reader:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Hello my mathematical genius friend. :) &lt;em&gt;[should I edit that out? *blush*]&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;I have been sent the following mathematical joke of sorts.  The person who sent it to me claims there are no flaws in it.  But obviously there has to be a flaw, because the conclusion is incorrect.  The problem is that I don't know how to explain the flaw---but I suspect it happens in that third line where it attempts to equate squared cents with squared dollars.  Is there any way that you could explain the flaw in such a way that a seventeen year old Norwegian would understand?  Don't worry, you don't have to say it in Norwegian, he speaks English. &lt;br /&gt;&lt;br /&gt;If you don't mind having a look at this and explaining, I would be ever so obliged.  And no pressure, but...pants may be on the line in this little bet I've entered into. &lt;br /&gt;&lt;br /&gt;1. $1= 100¢ (so $0.1 = 10¢)&lt;br /&gt;&lt;font color='red'&gt;2. And, 100¢ = 10¢²&lt;br /&gt;3. Then, 10¢² = $0.1²&lt;br /&gt;4. $0.1² = $0.01&lt;/font&gt;&lt;br /&gt;5. $0.01 = 1¢&lt;/blockquote&gt;&lt;br /&gt;The implied conclusion is&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;∴ 'a dime squared equals one penny'&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;Then we say '&lt;a href="http://dauclair.blogspot.com/2007/03/pirates-vs-ninjas.html"&gt;Q.E.D.&lt;/a&gt;'.&lt;br /&gt;&lt;br /&gt;Hm, if pants are on the line for my dear reader, I wonder what's on the line for &lt;span style="font-style:italic;"&gt;moi&lt;/span&gt;-self (that is faux-French) (and 'faux' is French)?  A review? Or two? Or three? Of &lt;a href="http://www.fanfiction.net/u/1727957/geophf"&gt;my stories&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;Let's leave my preening aside.&lt;br /&gt;&lt;br /&gt;So, who sees the fallacies above that lead to the absurd conclusion?&lt;br /&gt;&lt;br /&gt;If you do not see it, please think on this awhile before looking at the answer.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The answer&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;From basically the get-go this problem statement is erroneous and imprecise, but this comes from a fundamental laxity in understanding of what operators are and what operators do.  Certainly, the first premise is correct: One hundred pennies does indeed equate to one dollar, for &lt;br /&gt;&lt;blockquote&gt;1. 100¢ = $1&lt;/blockquote&gt;&lt;br /&gt;is a statement of fact about the conversion from one set of units (pennies or ¢) to another set (dollars or $).  But already the trickster plays fast and loose, for indeed:&lt;br /&gt;&lt;blockquote&gt;1. ... (so $0.1 = 10¢)&lt;/blockquote&gt;&lt;br /&gt;is still correct but the (implied) conclusion makes a statement about the square of dimes, not about the square of tenths of dollars.&lt;br /&gt;&lt;br /&gt;Do you see the fallacy now?&lt;br /&gt;&lt;br /&gt;No? Let's continue.&lt;br /&gt;&lt;br /&gt;So 1. is true, insofar as I can throw it, and days where my back gives out (ah! me poor bones!) that's not very far, but it's far enough for this problem statement, so long as it goes no farther than that.&lt;br /&gt;&lt;br /&gt;But it does.  *sigh*&lt;br /&gt;&lt;br /&gt;So now let's get into the lies:&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;2. 100¢ = (10¢)²&lt;/font&gt; &lt;em&gt;[parentheses implied and erroneous]&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;This is a lie.  It's a lie, lie, lie, lie, lie, lie, lie!&lt;br /&gt;&lt;br /&gt;Huh?&lt;br /&gt;&lt;br /&gt;The lie is this: a square of a thing is not the thing itself, and even if you know nothing about mathematics, you can prove this to yourself.  Socrates did it with an unlettered and untutored slave boy, and you are further along than what Socrates had to work with.&lt;br /&gt;&lt;br /&gt;So let's prove 2. false with an analogue.&lt;br /&gt;&lt;br /&gt;Take a foot rule (sorry, my readers who do not follow the British Imperial system, which, oddly enough, includes Brits these days, too) and a large piece of butcher paper.  Draw a line on the butcher paper measuring one foot.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;a. _ = 1 foot.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now, 'square' that line, by drawing three more lines to make a foot square on the butcher paper.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;b. ❏ = 1 foot square.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, is&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;c? 1 foot = 1 foot square&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Obviously not! for that would be to say:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;c? _ = ❏&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Or, put another way, '&lt;font color='red'&gt;one thing of one thing is equivalent to one thing of entirely a different thing&lt;/font&gt;'.  One gulp of water does not equal one gulp of bleach.  One I wish to have with my breakfast, the other, I do not, as my father very unfortunately discovered the hard way one not-so-fine morning.&lt;br /&gt;&lt;br /&gt;"But, but, but ..." you stutter angrily, "but isn't '10² = 100' a statement of fact?"&lt;br /&gt;&lt;br /&gt;Yes, indeed, it is, but please remember '10 ≠ 10 &lt;em&gt;things&lt;/em&gt;' is also a statement of fact. Number (with a capital 'N') is a class of classes as, e.g., &lt;em&gt;&lt;a href="http://books.google.com/books?id=p9YkUQZrncIC&amp;dq=introduction+to+mathematical+philosophy&amp;printsec=frontcover&amp;source=bn&amp;hl=en&amp;ei=TTn9S-jTE4KB8gaC2K29Cw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CDIQ6AEwAw#v=onepage&amp;q&amp;f=false"&gt;Introduction to Mathematical Philosophy&lt;/a&gt;&lt;/em&gt; so clearly and succinctly explains.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The &lt;a href="http://books.google.com/books?id=p9YkUQZrncIC&amp;dq=introduction+to+mathematical+philosophy&amp;printsec=frontcover&amp;source=bn&amp;hl=en&amp;ei=TTn9S-jTE4KB8gaC2K29Cw&amp;sa=X&amp;oi=book_result&amp;ct=result&amp;resnum=4&amp;ved=0CDIQ6AEwAw#v=onepage&amp;q&amp;f=false"&gt;link&lt;/a&gt; goes right to the book, all 228 pages of it.  It's a quick read, so please (re)read it.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So to state:&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;2. 100¢ = (10¢)²&lt;/font&gt; &lt;em&gt;[parentheses implied and erroneous]&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;is to state a falsehood.&lt;br /&gt;&lt;br /&gt;How do we correct it?  Well, by replacing the (implied) error with an explicit (corrected) ordering:&lt;br /&gt;&lt;blockquote&gt;2. 100¢ = 10²¢&lt;/blockquote&gt;&lt;br /&gt;Do you see the correction? It the former case, we erroneously squared the units along with the number, in the latter case we &lt;em&gt;do not&lt;/em&gt; square the units, we square the number solely.&lt;br /&gt;&lt;br /&gt;Do I need to go any further?  Or, do the fallacies fall out obviously in the rest of the assertions?&lt;br /&gt;&lt;br /&gt;For completeness sake, I will review each step.&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;3. (10¢)² = ($0.1)²&lt;/font&gt; &lt;em&gt;[parentheses implied and erroneous]&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;No. (10 pennies) squared does not equal (1 dime) squared.&lt;br /&gt;But, a statement of fact of conversion is that (10 pennies) = (1 dime), but that's as far as it goes, &lt;em&gt;and no farther.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;If we square pennies we have a new unit of measure called, I don't know: (¢²), and (¢²) does &lt;em&gt;not&lt;/em&gt; equal dimes.  Not in this world.&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;4. ($0.1)² = $0.01&lt;/font&gt; &lt;em&gt;[parentheses implied and erroneous]&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;Again, no.&lt;br /&gt;Again: $(0.1²) = $0.01, but again, that is as far as you can go with that statement.&lt;br /&gt;&lt;blockquote&gt;5. $0.01 = 1¢&lt;/blockquote&gt;&lt;br /&gt;is just a reformulation of the first statement and is true, yes, but redundant.&lt;br /&gt;&lt;br /&gt;Remember from &lt;a href="http://plato.stanford.edu/entries/frege-logic/"&gt;Frege's predicate calculus&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;q |- p &lt;em&gt;[read: 'q implied by p' or 'if p then q']&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;em&gt;[Shoot! why don't they have an 'implied by' HTML character?]&lt;/em&gt;&lt;br /&gt;But if:&lt;br /&gt;&lt;blockquote&gt;¬p &lt;em&gt;[read: 'not p' or 'p is not true (or provable)']&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;Then you can say anything you like for q, or, more correctly, you &lt;em&gt;cannot&lt;/em&gt; say anything &lt;em&gt;at all&lt;/em&gt; about q, because q does not depend on ¬p, it depends on p.&lt;br /&gt;&lt;br /&gt;So, as it were: 'If I had done the laundry, we wouldn't have had this argument' and 'I didn't do the laundry' means I don't have a leg to stand on about why we had this argument, honey.&lt;br /&gt;&lt;br /&gt;(Oops, sorry, ... but it's not like I have had this experience at all ...)&lt;br /&gt;&lt;br /&gt;And, to the point of this article: 'If a (10 one-hundredths of a dollar) squared were to equal (10 pennies) squared, then ...'&lt;br /&gt;&lt;br /&gt;Well, then anything, because '&lt;font color='red'&gt;(10 one-hundredths of a dollar) squared = (10 pennies) squared&lt;/font&gt;' is false.  So say away, because anything coming from a false premise is an absurd conclusion: whirled &lt;a href="http://www.blackeyedpeas.com/"&gt;(black eyed) peas&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Butterfly_effect"&gt;butterflies flapping&lt;/a&gt; in the &lt;a href="http://www.amazon.com"&gt;Amazon&lt;/a&gt;, and the &lt;a href="http://en.wikipedia.org/wiki/Principia_Discordia"&gt;Number 23&lt;/a&gt;.  They may be true enough in their own right, but you can say &lt;em&gt;nothing&lt;/em&gt; about them from the false premise.&lt;br /&gt;&lt;br /&gt;So, let's take the absurd conclusion:&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;∴ 'a dime squared equals one penny'&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;and reformulate it to be a true statement.&lt;br /&gt;&lt;br /&gt;Well, the first thing we have to do it to get rid of the '∴', so let's do that, and then state the plain facts:&lt;br /&gt;&lt;blockquote&gt;&lt;font&gt;'a dime squared equals one penny' is an absurdity.&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;a href="http://dauclair.blogspot.com/2007/03/pirates-vs-ninjas.html"&gt;Q.E.D.&lt;/a&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;What can we take away from this?&lt;br /&gt;&lt;br /&gt;Let's examine another absurity:&lt;br /&gt;&lt;blockquote&gt;&lt;font color='red'&gt;'Math is hard.'&lt;/font&gt;&lt;/blockquote&gt;&lt;br /&gt;No. &lt;br /&gt;&lt;br /&gt;No, my dear ladies and gentlemen, 'Math' isn't 'hard.' Math is simple. Math can even be easy, for we learned from the Greeks, after all, that Math is one of the humanities.  Math is simply a language.  A language that can describe things exactly as they are and exactly as they are not.  And precisely at that.  It can even describe &lt;a href="http://en.wikipedia.org/wiki/Fuzzy_set"&gt;imprecision precisely&lt;/a&gt;.  The 'hard'ness of mathematics comes from us, when we don't wish to be precise in what we are talking or thinking about.&lt;br /&gt;&lt;br /&gt;Being precise ... well, that can be hard, I suppose, so then perhaps it's more precise not to say '&lt;font color='red'&gt;Math is hard&lt;/font&gt;' but to say 'Life is hard.'&lt;br /&gt;&lt;br /&gt;Yes. That's true. 'Life is hard' as we choose to make it.&lt;br /&gt;&lt;br /&gt;Oh, well. I never promised you a &lt;a href="http://www.fanfiction.net/s/5668504/1/Reminiscence"&gt;Rose&lt;/a&gt; &lt;a href="http://www.fanfiction.net/s/4837797/1/Rose_by_a_Lemon_Tree"&gt;Garden&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-8339634600444486934?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/8339634600444486934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=8339634600444486934' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8339634600444486934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8339634600444486934'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2010/05/math-is-hard.html' title='Math is hard'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-8277363035802655493</id><published>2009-06-02T11:13:00.000-07:00</published><updated>2009-06-29T16:25:43.448-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unification'/><category scheme='http://www.blogger.com/atom/ns#' term='design patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='comonad'/><title type='text'>Realized Constants are Comonadic</title><content type='html'>An interesting problem that often arises is "to make" constants.  Put another way, it often happens that a system acquires information over time.  The system may wish to formalize what it has acquired by creating a constant value.&lt;br /&gt;&lt;br /&gt;Here's the problem, however: "Variables don't; Constants aren't"&lt;small&gt;&lt;sup&gt;citation?&lt;/sup&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Or, put another way:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;1. &lt;a href="http://www.cs.yale.edu/quotes.html"&gt;One man's constant is another man's variable&lt;/a&gt;.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;To make a constant sometime down the road, as it were, in languages that have logic variables is simplicity itself: once a variable is unified with a value, it keeps that value throughout that proof.&lt;br /&gt;&lt;br /&gt;In "pure" functional languages, that is, languages that do not have side effects, the same can be said.&lt;br /&gt;&lt;br /&gt;What about the rest of the world?  Take Java, for example.  One can make a variable keep its value by declaring that variable &lt;code&gt;final&lt;/code&gt;, but that is not helpful if we do not know what our constant value is to be at the time of object creation.&lt;br /&gt;&lt;br /&gt;In what scenario could this possibly occur?  We need a constant value, but we do not know what it is?&lt;br /&gt;&lt;br /&gt;Actually, this situation arises quite frequently.  Let's take a concrete example.  You have many databases in your database management system, and at compile time you do not know on which port your DBMS is running nor do you know which database the user wishes to query.  That's fine, you can lazily create the database connection and access the value through a method:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;2. &lt;a href="http://www.cs.yale.edu/quotes.html"&gt;Functions delay binding; data structures induce binding. Moral: Structure data late in the programming process&lt;/a&gt;. &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;But what's not fine is this: the user is data-mining, examining chunks at a time, occasionally calling for the next chunk.  How does one know that one has fallen off the end of the table?  A simple &lt;code&gt;SELECT&lt;/code&gt; on the maximum indexed key will tell you that, but to do that with every query?  This seems wasteful.  So, once we do the query once, let's just store that value in a variable with a flag to say we've already looked it up.&lt;br /&gt;&lt;br /&gt;That sounds suspiciously like a lazily initialized constant, right?&lt;br /&gt;&lt;br /&gt;But here's the rub: code that sets a flag allows for other code to unset it, just as code that sets a constant value allows other code to unset that.  Using just plain-old regular variables gives no guarantee that the variable, once set, stays set at that constant value.&lt;br /&gt;&lt;br /&gt;What to do?&lt;br /&gt;&lt;br /&gt;Well, what is the work-flow of this process?  We perform an action, checking that we are still within the bounds the valid domain, but the domain only becomes valid after program start, so we cannot make the bounds constant using the &lt;code&gt;final&lt;/code&gt; keyword on the variable.  This is a very common programming action ... sort of like ... dare I say ... a &lt;a href="http://en.wikipedia.org/wiki/Design_patterns"&gt;design pattern&lt;/a&gt;.  Gee, I wish there was one invented that did all this.&lt;br /&gt;&lt;br /&gt;In fact, there does exist such a pattern, and it comes from us via &lt;a href="http://en.wikipedia.org/wiki/Category_theory"&gt;Category Theory&lt;/a&gt;.  The programming language &lt;a href='http://haskell.org/'&gt;Haskell&lt;/a&gt; has incorporated elements of Category theory in its use of &lt;a href="http://www.haskell.org/all_about_monads/html/introduction.html#what"&gt;monads&lt;/a&gt; and &lt;a href="http://www.haskell.org/arrows/"&gt;arrows&lt;/a&gt;, but the downside of these ways of thinking about computation is that one must "lift" the entire computation into that domain, transforming the original computation to work in that regime.&lt;br /&gt;&lt;br /&gt;No, what is needed is something less intrusive, and I found that less intrusive thing when I read an article by &lt;a href="http://blog.sigfpe.com/"&gt;sigfpe&lt;/a&gt; on &lt;a href="http://comonad.com/reader/"&gt;comonadic&lt;/a&gt; &lt;a href="http://blog.sigfpe.com/2008/06/categories-of-polynomials-and-comonadic.html"&gt;plumbing&lt;/a&gt;.  In this article he describes three different ways of looking at constants:  1. as a constant, 2. as the &lt;tt&gt;Reader Monad&lt;/tt&gt;, 3. or as the &lt;tt&gt;Reader Comonad&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;The first one is sometimes untenable, given the programming need, and doesn't work for our case.&lt;br /&gt;&lt;br /&gt;The second one is useful if one is already programming in a monad.  Umm ... how many OO programmers use monads?  Hands up.&lt;br /&gt;&lt;br /&gt;[sound of crickets] ... thought so.&lt;br /&gt;&lt;br /&gt;The third one allows one to use the constant on demand.  And here's the thing, the comonad is very easily comprehended: it has a value that can be &lt;code&gt;extract&lt;/code&gt;ed "down" from the comonad, it allows a value to be &lt;code&gt;extend&lt;/code&gt;ed over the comonad.&lt;br /&gt;&lt;br /&gt;This sounds, in OO parlance, very much like an object.  Let's ignore the extentionability of the comonad for now and simply look at extraction (this narrowed functionality is a thing in and of itself.  Objects of this type are called &lt;tt&gt;&lt;a href="http://conal.net/blog/posts/sequences-streams-and-segments/"&gt;Copointed&lt;/a&gt;&lt;/tt&gt;, but let us not be too dogmatic here).  Creating such a type is simplicity itself:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; public interface &lt;tt&gt;Comonad&amp;lt;T&gt;&lt;/tt&gt; { public &lt;tt&gt;T&lt;/tt&gt; extract(); }&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Um, yawn?&lt;br /&gt;&lt;br /&gt;But that is the power of pattern language: not the ability to create these incredibly complex things in a controlled way (they do do that), but the ability to recognize that such and so is a pattern and then encapsulate behavior into the pattern.&lt;br /&gt;&lt;br /&gt;Using the comonad pattern, we need simply to make our "maximum row number of Table x" an implementation of the &lt;tt&gt;Comonad&lt;/tt&gt; interface, and then, when we do have enough information to create the database connection (that is, we now have our domain in which our constant resides), we instantiate the comonadic object (which &lt;em&gt;is&lt;/em&gt; that domain).  Whenever &lt;code&gt;extract&lt;/code&gt; is called, it simply returns the constant value required, with the implementation that it does a database look up the first time, then it does the internal constant value look up all other times.  Since the &lt;tt&gt;Comonad&lt;/tt&gt; interface does not have methods to change its internals (here), so long as one has the copointed object, the value &lt;code&gt;extract&lt;/code&gt; has a guarantee that it remains constant.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This article examined a commonly recurring problem: one needs to constify a value at some point during a program run and guarantee that it remain constant after being created.  A simplification of the comonad was offered as a pattern that is simple to define and to implement.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-8277363035802655493?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/8277363035802655493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=8277363035802655493' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8277363035802655493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8277363035802655493'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2009/06/realized-constants-are-comonadic.html' title='Realized Constants are Comonadic'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-5160123325060668201</id><published>2008-09-29T18:21:00.000-07:00</published><updated>2008-09-30T05:43:34.506-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='knowledge engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><title type='text'>Animal as RDR, part III</title><content type='html'>&lt;strong&gt;Examples: Building, running and modifying RDR systems&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The previous entries showed the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-as-rdr-part-ii.html'&gt;implementation&lt;/a&gt; of the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-rdr-implementation-study.html'&gt;model&lt;/a&gt; of a simple Ripple-Down Rules (RDR) system. This entry will show how to implement the rules for such a system from scratch as well as how to run and then to modify such a system.  Again, we are using the computer game Animal as the basis of these examples.&lt;br /&gt;&lt;br /&gt;Let's start off by implementing RDR system modelled in the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-rdr-implementation-study.html'&gt;first entry&lt;/a&gt; on this topic.  But first, we need a couple of improvements.  The &lt;code&gt;addRule&lt;/code&gt; I had originally implemented wasn't an example for ease of use as it was ...&lt;blockquote&gt;&lt;pre&gt;&lt;font color='red'&gt;] addRule :: BinDir&lt;br /&gt;]            &amp;rarr; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v&lt;br /&gt;]            &amp;rarr; &lt;tt&gt;Environment&lt;/tt&gt; k v b c&lt;br /&gt;]            &amp;rarr; &lt;tt&gt;Condition&lt;/tt&gt; a (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;]            &amp;rarr; &lt;tt&gt;Conclusion&lt;/tt&gt; b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;]            &amp;rarr; &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v&lt;br /&gt;] addRule dir (&lt;tt&gt;Zip&lt;/tt&gt; hist branch) env cond concl &lt;br /&gt;]         = &lt;kbd&gt;let&lt;/kbd&gt; rule = &lt;tt&gt;Branch&lt;/tt&gt; (&lt;tt&gt;Rule&lt;/tt&gt; cond concl) &lt;tt&gt;Leaf&lt;/tt&gt; &lt;tt&gt;Leaf&lt;/tt&gt;&lt;br /&gt;]               newbr = fromJust $ mutate dir rule branch&lt;br /&gt;]               newtree = &lt;kbd&gt;return&lt;/kbd&gt; $ settle (&lt;tt&gt;Zip&lt;/tt&gt; hist newbr)&lt;br /&gt;]           &lt;kbd&gt;in&lt;/kbd&gt;  &lt;tt&gt;RuleEnv&lt;/tt&gt; newtree env&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;... so I changed it so that it fit more neatly into building rules in sequence:&lt;blockquote&gt;&lt;pre&gt;&gt; addRule :: &lt;tt&gt;BinDir&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Rule&lt;/tt&gt; a b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt;            &amp;rarr; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v &amp;rarr; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v&lt;br /&gt;&gt; addRule dir rule (&lt;tt&gt;Zip&lt;/tt&gt; hist branch)&lt;br /&gt;&gt;         = &lt;kbd&gt;let&lt;/kbd&gt; ruleB = &lt;tt&gt;Branch&lt;/tt&gt; rule &lt;tt&gt;Leaf&lt;/tt&gt; &lt;tt&gt;Leaf&lt;/tt&gt;&lt;br /&gt;&gt;           &lt;kbd&gt;in&lt;/kbd&gt;  &lt;tt&gt;Zip&lt;/tt&gt; hist (mutate dir ruleB branch)&lt;/pre&gt;&lt;/blockquote&gt;This new implementation has now replaced the previous one in the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-as-rdr-part-ii.html'&gt;implementation entry&lt;/a&gt;.  Also, constructing &lt;tt&gt;Rule&lt;/tt&gt;s themselves was a bit labour-intensive, so I've added the following function to simplify building simple rules:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;SimpleRule&lt;/tt&gt; = &lt;tt&gt;Rule String String String&lt;/tt&gt; &lt;br /&gt;&gt;                        (&lt;tt&gt;Knowledge String String&lt;/tt&gt;)&lt;br /&gt;&lt;br /&gt;&gt; mkRule :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;SimpleRule&lt;/tt&gt;&lt;br /&gt;&gt; mkRule key ans = &lt;tt&gt;Rule&lt;/tt&gt; (present key) (assume ans)&lt;/pre&gt;&lt;/blockquote&gt;Also, recall that:&lt;blockquote&gt;&lt;code&gt;(&gt;&gt;|) :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m a &amp;rarr; (a &amp;rarr; b) &amp;rarr; m b&lt;/code&gt;&lt;/blockquote&gt;This function simply reorders the arguments of &lt;code&gt;liftM&lt;/code&gt;, so why have it?  I find it useful in the flow of building monadic systems, as demonstrated below.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Building&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;And with that, let us build our Animal guessing game knowledge base:&lt;blockquote&gt;&lt;pre&gt;&gt; animalTree :: &lt;tt&gt;Zipper BinDir&lt;/tt&gt; (&lt;tt&gt;BinaryTree SimpleRule&lt;/tt&gt;)&lt;br /&gt;&gt;               &amp;rarr; &lt;tt&gt;Zipper BinDir&lt;/tt&gt; (&lt;tt&gt;BinaryTree SimpleRule&lt;/tt&gt;)&lt;br /&gt;&gt; animalTree tree = fromJust &lt;br /&gt;&gt;                   (&lt;kbd&gt;return&lt;/kbd&gt; tree &gt;&gt;|&lt;br /&gt;&gt;                    addRule &lt;tt&gt;L&lt;/tt&gt; (mkRule "has four legs" "pony") &gt;&gt;=&lt;br /&gt;&gt;                    advance &lt;tt&gt;L&lt;/tt&gt; &gt;&gt;|&lt;br /&gt;&gt;                    addRule &lt;tt&gt;L&lt;/tt&gt; (mkRule "barks" "dog") &gt;&gt;|&lt;br /&gt;&gt;                    addRule &lt;tt&gt;R&lt;/tt&gt; (mkRule "swims" "fish") &gt;&gt;=&lt;br /&gt;&gt;                    advance &lt;tt&gt;L&lt;/tt&gt; &gt;&gt;|&lt;br /&gt;&gt;                    addRule &lt;tt&gt;R&lt;/tt&gt; (mkRule "purrs" "cat") &gt;&gt;=&lt;br /&gt;&gt;                    withdraw &gt;&gt;=&lt;br /&gt;&gt;                    advance &lt;tt&gt;R&lt;/tt&gt; &gt;&gt;|&lt;br /&gt;&gt;                    addRule &lt;tt&gt;R&lt;/tt&gt; (mkRule "spins web" "spider") &gt;&gt;|&lt;br /&gt;&gt;                    reset)&lt;/pre&gt;&lt;/blockquote&gt;The function &lt;code&gt;reset&lt;/code&gt; is from the &lt;code&gt;&lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Zipper&lt;/tt&gt;&lt;/code&gt; module:&lt;blockquote&gt;&lt;pre&gt;&gt; reset :: (&lt;tt&gt;Mutable&lt;/tt&gt; c dir c, &lt;tt&gt;Transitive&lt;/tt&gt; c dir)&lt;br /&gt;&gt;             &amp;rArr; &lt;tt&gt;Zipper&lt;/tt&gt; dir c &amp;rarr; &lt;tt&gt;Zipper&lt;/tt&gt; dir c&lt;br /&gt;&gt; reset z@(&lt;tt&gt;Zip&lt;/tt&gt; [] _) = z&lt;br /&gt;&gt; reset (&lt;tt&gt;Zip&lt;/tt&gt; ((dir, h):t) elt) = reset (&lt;tt&gt;Zip&lt;/tt&gt; t $ mutate dir elt h)&lt;/pre&gt;&lt;/blockquote&gt;Looking at &lt;code&gt;animalTree&lt;/code&gt; above, I say with unmasked pride that I feel &lt;code&gt;(&gt;&gt;|)&lt;/code&gt; shows its hidden strength: I could not imagine puzzling out the proper way to write the above definition using &lt;code&gt;liftM&lt;/code&gt; and have it follow the natural flow that it does with its current implementation.  Also note that it is vital that &lt;code&gt;reset&lt;/code&gt; be called after a set of changes to a knowledge base occur, to reset (obviously) the focus to the top-level (default) rule, and to correct the tree containing that knowledge.  &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Running&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Now that we have our &lt;code&gt;animalTree&lt;/code&gt;, we need one more function to extract the result (follow the &lt;tt&gt;Conclusion&lt;/tt&gt;) of &lt;code&gt;runRule&lt;/code&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; runConcl :: &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v &amp;rarr; c&lt;br /&gt;&gt; runConcl (&lt;tt&gt;RuleEnv&lt;/tt&gt; _ (&lt;tt&gt;Env&lt;/tt&gt; ks (&lt;tt&gt;Concl&lt;/tt&gt; _ f))) = f ks&lt;/pre&gt;&lt;/blockquote&gt;Now, we could set up an interactive question-answer session to tease the animal we are guessing from our hidden thoughts, but, since interactive I/O is a sin in functional languages (see the &lt;a href='http://homepages.cwi.nl/~tromp/cl/lazy-k.html'&gt;fall from grace in Lazy K&lt;/a&gt;), let's "pretend" our way through an interactive session, recording the results of the questions into the &lt;tt&gt;Environment&lt;/tt&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; rtests :: &lt;tt&gt;IO&lt;/tt&gt; ()&lt;br /&gt;&gt; rtests = &lt;kbd&gt;let&lt;/kbd&gt; &lt;tt&gt;RuleEnv&lt;/tt&gt; tree env  = initKB "default" (assume "none")&lt;br /&gt;&gt;              newTree = animalTree tree&lt;br /&gt;&gt;              spider = updateEnv "spins web" "true" env&lt;br /&gt;&gt;              chat   = updateEnv "has four legs" "true" $&lt;br /&gt;&gt;                                 updateEnv "purrs" "true" env&lt;br /&gt;&gt;              spy = runConcl (answer $ &lt;tt&gt;RuleEnv&lt;/tt&gt; newTree spider)&lt;br /&gt;&gt;              cat = runConcl (answer $ &lt;tt&gt;RuleEnv&lt;/tt&gt; newTree chat)&lt;br /&gt;&gt;          &lt;kbd&gt;in  do print&lt;/kbd&gt; newTree&lt;br /&gt;&gt;                 &lt;kbd&gt;print&lt;/kbd&gt; spy&lt;br /&gt;&gt;                 &lt;kbd&gt;print&lt;/kbd&gt; cat&lt;/pre&gt;&lt;/blockquote&gt;As expected, &lt;code&gt;spy&lt;/code&gt; is &lt;code&gt;"spider"&lt;/code&gt; (in answer to the question "Does it spin a web?"), and &lt;code&gt;cat&lt;/code&gt; is &lt;code&gt;"cat"&lt;/code&gt; (in answer to the questions "Does it have four legs?" followed by "Does it purr?").&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Modifying&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;All is well and good with the world, yes?  Certainly, when we receive the expected answers from our knowledge base, but let's explore the world a bit beyond what we've captured.  Not everything that swims is a fish:&lt;blockquote&gt;&lt;pre&gt;&gt; fishey = &lt;kbd&gt;let&lt;/kbd&gt; &lt;tt&gt;RuleEnv&lt;/tt&gt; tree env  = initKB "default" (assume "none")&lt;br /&gt;&gt;              newTree = animalTree tree&lt;br /&gt;&gt;              duck   = updateEnv "swims" "true" &lt;br /&gt;&gt;                                 $ updateEnv "flies" "true" env&lt;br /&gt;&gt;              noDuck = runConcl (answer $ &lt;tt&gt;RuleEnv&lt;/tt&gt; newTree duck)&lt;br /&gt;&gt;          &lt;kbd&gt;in  print&lt;/kbd&gt; noDuck&lt;/pre&gt;&lt;/blockquote&gt;We find that &lt;code&gt;noDuck&lt;/code&gt; is a &lt;code&gt;"fish"&lt;/code&gt;.  Perhaps it's a "flying fish", but it definitely wasn't the animal we were guessing, so we need to update our knowledge base to give us the desired answer.  Fortunately, the system returns the &lt;tt&gt;Rule&lt;/tt&gt; that rendered the &lt;tt&gt;Conclusion&lt;/tt&gt;, so modifying the system proceeds directly:&lt;blockquote&gt;&lt;pre&gt;&gt; duckey = &lt;kbd&gt;let&lt;/kbd&gt; &lt;tt&gt;RuleEnv&lt;/tt&gt; tree env  = initKB "default" (assume "none")&lt;br /&gt;&gt;              newTree = animalTree tree&lt;br /&gt;&gt;              duck   = updateEnv "swims" "true" &lt;br /&gt;&gt;                                 $ updateEnv "flies" "true" env&lt;br /&gt;&gt;              re@(RuleEnv noDuckTree _) = answer $ &lt;tt&gt;RuleEnv&lt;/tt&gt; newTree duck&lt;br /&gt;&gt;              noDuck = runConcl re&lt;br /&gt;&gt;              duckTree = addRule &lt;tt&gt;L&lt;/tt&gt; (mkRule "flies" "duck") noDuckTree&lt;br /&gt;&gt;              ducky = runConcl (answer $ RuleEnv duckTree duck)&lt;br /&gt;&gt;          &lt;kbd&gt;in  print&lt;/kbd&gt; (noDuck, ducky)&lt;/pre&gt;&lt;/blockquote&gt;With the modification in place, that is, the addition of the new &lt;code&gt;EXCEPT&lt;/code&gt; &lt;tt&gt;Rule&lt;/tt&gt;, we find that the animal that swims and flies is, indeed, a &lt;code&gt;"duck"&lt;/code&gt;, as expected.  That's &lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;ducky&lt;/code&gt;!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Knowledge in context&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Of course, there is the flying fish conundrum, so a better ordering would be to have the &lt;tt&gt;Conclusion&lt;/tt&gt; of that &lt;tt&gt;Rule&lt;/tt&gt; &lt;em&gt;actually be&lt;/em&gt; &lt;code&gt;"flying fish"&lt;/code&gt; and its &lt;code&gt;EXCEPT&lt;/code&gt; clause (with the &lt;tt&gt;Condition&lt;/tt&gt; being something like &lt;code&gt;"webbed feet"&lt;/code&gt; or &lt;code&gt;"feathers"&lt;/code&gt;) rendering the &lt;code&gt;"duck"&lt;/code&gt; &lt;tt&gt;Conclusion&lt;/tt&gt;.  While we're on the topic of structuring knowledge, not everything that purrs is a cat.  The knowledge base could have had a very different structure if the &lt;tt&gt;Condition&lt;/tt&gt; of the first &lt;tt&gt;Rule&lt;/tt&gt; was &lt;code&gt;"purrs"&lt;/code&gt;.  &lt;a href='http://en.wikipedia.org/wiki/Trekkie'&gt;Trekkers&lt;/a&gt; know the answer to that one: &lt;code&gt;"&lt;a href='http://en.wikipedia.org/wiki/Tribble_(Star_Trek)'&gt;tribble&lt;/a&gt;"&lt;/code&gt;, obviously!  The follow-on &lt;code&gt;EXCEPT&lt;/code&gt; clause (with the &lt;tt&gt;Condition&lt;/tt&gt; of &lt;code&gt;"four legs"&lt;/code&gt;) would then clarify to the feline nature.&lt;br /&gt;&lt;br /&gt;This demonstrates &lt;em&gt;knowledge in context&lt;/em&gt;, where in one context, the context of "having four legs", the attribute of purring leads to &lt;code&gt;"cat"&lt;/code&gt;, but in another context (the blank context, but that context could be elaborated with some &lt;tt&gt;Rule&lt;/tt&gt;s that put us in the context of the &lt;a href='http://www.startrek.com/startrek/view/index.html'&gt;Star Trek&lt;/a&gt;, um, &lt;em&gt;multiverse?&lt;/em&gt;), the very same attribute leads to &lt;code&gt;"tribble"&lt;/code&gt;.  Under this new context, &lt;code&gt;"four legs"&lt;/code&gt; leads back to our &lt;em&gt;"&lt;a href='http://www.chatchapeau.com/'&gt;chat chapeau&lt;/a&gt;"&lt;/em&gt; (that is Viennese) [I am really running &lt;a href='http://bungie.wikia.com/wiki/Rampancy'&gt;rampant&lt;/a&gt; with my &lt;a href='http://en.wikipedia.org/wiki/Pataphysics'&gt;`pataphorisms&lt;/a&gt;, I do apologize and will work to check myself, but topic of &lt;a href='http://en.wikipedia.org/wiki/Epistemology'&gt;επιστήμη λόγος&lt;/a&gt; does rather lend itself to such openings [which I have relentlessly pursued ... again!]]  Furthermore, the &lt;a href='http://en.wikipedia.org/wiki/Quiddity'&gt;quiddity&lt;/a&gt; of &lt;code&gt;"four legs"&lt;/code&gt; is, itself, context-based.  In one sense it leads to every little girl's dream (a &lt;code&gt;"pony"&lt;/code&gt;) and following (&lt;code&gt;EXCEPT&lt;/code&gt;ing) that, several other species, and in another context, it leads to non-tribble purring creatures.  This is a rather fundamental restructuring of our presumptions from the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-rdr-implementation-study.html'&gt;first article on this topic&lt;/a&gt;.  I don't have a simple function that restructures knowledge assumptions in fundamental ways; I don't see the benefit of having one, so let's simply rewrite our knowledge base from scratch with our gained experience:&lt;blockquote&gt;&lt;pre&gt;&gt; startrek tree = fromJust&lt;br /&gt;&gt;                 (&lt;kbd&gt;return&lt;/kbd&gt; tree &gt;&gt;|&lt;br /&gt;&gt;                  addRule &lt;tt&gt;L&lt;/tt&gt; (mkRule "purrs" "tribble") &gt;&gt;=&lt;br /&gt;&gt;                  advance &lt;tt&gt;L&lt;/tt&gt; &gt;&gt;|&lt;br /&gt;&gt;                  addRule &lt;tt&gt;L&lt;/tt&gt; (mkRule "has four legs" "cat") &gt;&gt;|&lt;br /&gt;&gt;                  addTree &lt;tt&gt;R&lt;/tt&gt; (firstRule (animalTree tree)) &gt;&gt;|&lt;br /&gt;&gt;                  reset)&lt;br /&gt;&gt;      where addTree dir (&lt;tt&gt;Zip&lt;/tt&gt; _ branch) (&lt;tt&gt;Zip&lt;/tt&gt; hist tree)&lt;br /&gt;&gt;                      = &lt;tt&gt;Zip&lt;/tt&gt; hist $ mutate dir branch tree&lt;br /&gt;&gt;            firstRule = fromJust . advance &lt;tt&gt;L&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;Not as painful as I thought!  There are a couple of points to note, however:&lt;ol&gt;&lt;li&gt;The path to discovering a &lt;code&gt;"cat"&lt;/code&gt; is duplicated, redundantly.  This is fine, however: real knowledge is messy and contains redundancies, and this redundancy doesn't impact the (speed) efficiency of this knowledge base in any way; and,&lt;/li&gt;&lt;li&gt;We are back to missing our &lt;code&gt;"duck"&lt;/code&gt;.  I leave that as an exercise to you to re-add.&lt;/li&gt;&lt;/ol&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This concludes the series of articles on the explanation, implementation and demonstration of a simple Ripple-Down Rules (RDR) system.  In these articles we showed that such systems are easy to implement in Haskell and then to use.  Knowledge management, in and of itself, is a rather deep and tricky topic (we have hinted at such trickiness in our "&lt;a href='http://www.startrek.com/startrek/view/library/episodes/TOS/detail/68744.html'&gt;Trouble with Tribbles&lt;/a&gt;"), but RDR, using the concept of &lt;em&gt;knowledge in context&lt;/em&gt; provides a method that allows modelling this knowledge more directly and allows manipulation of assumptions without adding too much difficulty to the task of knowledge engineering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-5160123325060668201?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/5160123325060668201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=5160123325060668201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5160123325060668201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5160123325060668201'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/animal-as-rdr-part-iii.html' title='Animal as RDR, part III'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-6703121488885077319</id><published>2008-09-19T11:32:00.000-07:00</published><updated>2008-09-30T05:45:04.337-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='knowledge engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><title type='text'>Animal as RDR, part II</title><content type='html'>&lt;strong&gt;Implementation study&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-rdr-implementation-study.html'&gt;In the last entry&lt;/a&gt;, we introduced what RDR (ripple-down rules) are and reviewed the types that comprise an example system.  This entry will show how those types are used to implement such a system.&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;RDRFinding&lt;/tt&gt; where&lt;/kbd&gt;&lt;/code&gt;&lt;/blockquote&gt;This module scans the RDR tree in context to give BOTH the best-fitting conclusion AND the final Branch that led to the ultimate conclusion (in the form of a zipper so that the branch may be replace in place using standard operations on the zipper).&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;RDRTypes&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Transitive&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Zipper&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;BinaryTree&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Map&lt;/tt&gt; (&lt;tt&gt;Map&lt;/tt&gt;)&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; qualified &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Map&lt;/tt&gt; as &lt;tt&gt;Map&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;.&lt;tt&gt;State&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Maybe&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;You have already encountered the above imported modules, but the next two modules need an introduction.  The first&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;.&lt;tt&gt;Utils&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;contains my weird and wonderful syntax when I'm using monads for parsing or logic tasks.  The &lt;a href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-ii-state-monad.html'&gt;parsing syntax&lt;/a&gt; you've seen before (see the critique), but I do add one new syntactic construct:&lt;blockquote&gt;&lt;code&gt;(&gt;&gt;|) :: m a &amp;rarr; (a &amp;rarr; b) &amp;rarr; m b&lt;/code&gt;&lt;/blockquote&gt;because I'm always doing "&lt;code&gt;m &gt;&gt;= &lt;kbd&gt;return&lt;/kbd&gt; . f&lt;/code&gt;", and &lt;code&gt;liftM&lt;/code&gt; seems to feel oddly backwards when I'm visualizing data flow.  The next&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Mutable&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;provides a generic operation for changing a data structure:&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;class&lt;/kbd&gt; &lt;tt&gt;Mutable&lt;/tt&gt; t dir val | t &amp;rarr; dir, t &amp;rarr; val &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;   mutate :: dir &amp;rarr; val &amp;rarr; t &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; t&lt;/pre&gt;&lt;/blockquote&gt;So, what's the game?  We have an &lt;tt&gt;Environment&lt;/tt&gt; (a set of attributed values) combined with a &lt;tt&gt;RuleTree&lt;/tt&gt; into the &lt;tt&gt;State Monad&lt;/tt&gt;.  What we do is guide the values in the environment through the rule tree (where a successful &lt;tt&gt;Condition&lt;/tt&gt; chooses the &lt;code&gt;EXCEPT&lt;/code&gt; branch and displaces the currently saved &lt;tt&gt;Conclusion&lt;/tt&gt; with the one associated with this &lt;tt&gt;Rule&lt;/tt&gt;, and conversely if the &lt;tt&gt;Condition&lt;/tt&gt; fails, the &lt;code&gt;ELSE&lt;/code&gt; branch is selected, without displacing the currently saved &lt;tt&gt;Conclusion&lt;/tt&gt;).  When we reach a &lt;tt&gt;Leaf&lt;/tt&gt;, we return our current position in the tree (the current state of the &lt;tt&gt;Zipper&lt;/tt&gt;) along with the last valid &lt;tt&gt;Conclusion&lt;/tt&gt;.  All this is done by &lt;code&gt;runRule&lt;/code&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; runRule :: &lt;tt&gt;RuleFinding&lt;/tt&gt; a b c k v&lt;br /&gt;&gt; runRule = get &gt;&gt;= &amp;lambda; (&lt;tt&gt;RuleEnv&lt;/tt&gt; root env) . runRule' root env&lt;br /&gt;&lt;br /&gt;&gt; runRule' :: &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v &amp;rarr; &lt;tt&gt;Environment&lt;/tt&gt; k v b c&lt;br /&gt;&gt;                                &amp;rarr; &lt;tt&gt;RuleFinding&lt;/tt&gt; a b c k v&lt;br /&gt;&gt; runRule' tree env@(&lt;tt&gt;Env&lt;/tt&gt; ks curr)&lt;br /&gt;&gt;         = branch tree &gt;&gt;: &amp;lambda; (cond, conc) .&lt;br /&gt;&gt;           &lt;kbd&gt;let&lt;/kbd&gt; (dir, concl) = liftZdir (testCond cond env conc)&lt;br /&gt;&gt;           &lt;kbd&gt;in&lt;/kbd&gt;  advance dir tree &gt;&gt;: &amp;lambda; path .&lt;br /&gt;&gt;               put (&lt;tt&gt;RuleEnv&lt;/tt&gt; path (&lt;tt&gt;Env&lt;/tt&gt; ks concl)) &gt;&gt; runRule&lt;br /&gt;&gt;    where x &gt;&gt;: f = tryS curr x f&lt;/pre&gt;&lt;/blockquote&gt;&lt;em&gt;Whew!&lt;/em&gt;  This is a mouthful in the number of functions it introduces, but conceptually, &lt;code&gt;runRule&lt;/code&gt; is rather straightforward.  Let's break it down.&lt;br /&gt;&lt;br /&gt;The function &lt;code&gt;runRule&lt;/code&gt;, itself, merely destructures the &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; term, passing that information to &lt;code&gt;runRule'&lt;/code&gt;, so let's move right on to that worker function.  First, let's examine the funny syntactic construct, &lt;code&gt;(&gt;&gt;:)&lt;/code&gt; &amp;mdash; what is this monadic operator doing?  We see from its definition that it calls &lt;code&gt;tryS&lt;/code&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; tryS :: a &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; b &amp;rarr; (b &amp;rarr; &lt;tt&gt;State&lt;/tt&gt; c a) &amp;rarr; &lt;tt&gt;State&lt;/tt&gt; c a&lt;br /&gt;&gt; tryS x may f = &lt;kbd&gt;maybe&lt;/kbd&gt; (&lt;kbd&gt;return&lt;/kbd&gt; x) f may&lt;/pre&gt;&lt;/blockquote&gt;So, &lt;code&gt;tryS&lt;/code&gt; lifts the &lt;tt&gt;State Monad&lt;/tt&gt; into semideterminism (using the &lt;tt&gt;Maybe Monad&lt;/tt&gt;).  As an aside, perhaps, then, &lt;code&gt;runRule'&lt;/code&gt; could be rewritten as a &lt;tt&gt;StateT&lt;/tt&gt; over the &lt;tt&gt;Maybe Monad&lt;/tt&gt; ... perhaps an intrepid reader will gain a &amp;perp;-trophy for an implementation and explanation?&lt;br /&gt;&lt;br /&gt;Using that monadic operator, &lt;code&gt;(&gt;&gt;:)&lt;/code&gt;, we get the current &lt;code&gt;branch&lt;/code&gt; in focus (bailing if the focus is on a &lt;tt&gt;Leaf&lt;/tt&gt;) ...&lt;blockquote&gt;&lt;pre&gt;&gt; branch :: &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v&lt;br /&gt;&gt;                &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; (&lt;tt&gt;Condition&lt;/tt&gt; a (&lt;tt&gt;Knowledge&lt;/tt&gt; k v), &lt;br /&gt;&gt;                          &lt;tt&gt;Conclusion&lt;/tt&gt; b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v))&lt;br /&gt;&gt; branch (&lt;tt&gt;Zip&lt;/tt&gt; _ (&lt;tt&gt;Branch&lt;/tt&gt; (&lt;tt&gt;Rule&lt;/tt&gt; cond conc) _ _)) = &lt;tt&gt;Just&lt;/tt&gt; (cond, conc)&lt;br /&gt;&gt; branch (&lt;tt&gt;Zip&lt;/tt&gt; _ &lt;tt&gt;Leaf&lt;/tt&gt;)                          = &lt;tt&gt;Nothing&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;... then we test the condition at that &lt;tt&gt;Branch&lt;/tt&gt; ...&lt;blockquote&gt;&lt;pre&gt;&gt; testCond :: &lt;tt&gt;Condition&lt;/tt&gt; a (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt;             &amp;rarr; &lt;tt&gt;Environment&lt;/tt&gt; k v ca cb&lt;br /&gt;&gt;             &amp;rarr; &lt;tt&gt;Conclusion&lt;/tt&gt; ca cb (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt;             &amp;rarr; &lt;tt&gt;Either&lt;/tt&gt; (&lt;tt&gt;Environment&lt;/tt&gt; k v ca cb)&lt;br /&gt;&gt;                       (&lt;tt&gt;Environment&lt;/tt&gt; k v ca cb)&lt;br /&gt;&gt; testCond (&lt;tt&gt;Cond&lt;/tt&gt; _ test) env@(&lt;tt&gt;Env&lt;/tt&gt; kb _) conc1 &lt;br /&gt;&gt;          | test kb   = &lt;tt&gt;Left&lt;/tt&gt; $ &lt;tt&gt;Env&lt;/tt&gt; kb conc1&lt;br /&gt;&gt;          | &lt;kbd&gt;otherwise&lt;/kbd&gt; = &lt;tt&gt;Right&lt;/tt&gt; env&lt;br /&gt;&lt;br /&gt;&gt; liftZdir :: &lt;tt&gt;Either&lt;/tt&gt; (&lt;tt&gt;Environment&lt;/tt&gt; k v ca cb) &lt;br /&gt;&gt;                    (&lt;tt&gt;Environment&lt;/tt&gt; k v ca cb)&lt;br /&gt;&gt;             &amp;rarr; (BinDir, &lt;tt&gt;Conclusion&lt;/tt&gt; ca cb (&lt;tt&gt;Knowledge&lt;/tt&gt; k v))&lt;br /&gt;&gt; liftZdir test = &lt;kbd&gt;either&lt;/kbd&gt; (&amp;lambda; (&lt;tt&gt;Env&lt;/tt&gt; _ c) . (&lt;tt&gt;L&lt;/tt&gt;, c))&lt;br /&gt;&gt;                        (&amp;lambda; (&lt;tt&gt;Env&lt;/tt&gt; _ c) . (&lt;tt&gt;R&lt;/tt&gt;, c))&lt;br /&gt;&gt;                        test&lt;/pre&gt;&lt;/blockquote&gt;I do this little &lt;em&gt;pas de deux&lt;/em&gt; between &lt;code&gt;testCond&lt;/code&gt; and &lt;code&gt;liftZdir&lt;/code&gt; because somehow it just feels right to use the &lt;tt&gt;Either&lt;/tt&gt; type here.  Perhaps, sometime later &lt;a href='http://haskell.org/arrows'&gt;Arrows&lt;/a&gt; will come into play.  At any rate, &lt;code&gt;liftZdir . testCond&lt;/code&gt; can be considered one function that returns the appropriate leg of the branch to continue finding the best viable &lt;tt&gt;Conclusion&lt;/tt&gt;, as well as the best current &lt;tt&gt;Conclusion&lt;/tt&gt; reached from applying the &lt;tt&gt;Environment&lt;/tt&gt; to the &lt;tt&gt;Condition&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Given that information, we now &lt;code&gt;advance&lt;/code&gt; down that &lt;code&gt;path&lt;/code&gt;, updating the state, and continue to test recursively, until we reach a &lt;tt&gt;Leaf&lt;/tt&gt;, at which point we have our answer (the ultimate viable &lt;tt&gt;Conclusion&lt;/tt&gt;).&lt;br /&gt;&lt;br /&gt;If we're happy with that answer, we call &lt;code&gt;runRule&lt;/code&gt; with a new transaction (in other words, a fresh &lt;tt&gt;Environment&lt;/tt&gt;), and the &lt;tt&gt;Zipper&lt;/tt&gt; pointing back at the top of the &lt;tt&gt;RuleTree&lt;/tt&gt;.  If we're not happy, then we're given the ability to add a new &lt;tt&gt;Rule&lt;/tt&gt; to the &lt;tt&gt;RuleTree&lt;/tt&gt;.  We do this with &lt;code&gt;addRule&lt;/code&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; addRule :: &lt;tt&gt;BinDir&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Rule&lt;/tt&gt; a b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt;            &amp;rarr; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v &amp;rarr; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v&lt;br /&gt;&gt; addRule dir rule (&lt;tt&gt;Zip&lt;/tt&gt; hist branch)&lt;br /&gt;&gt;         = &lt;kbd&gt;let&lt;/kbd&gt; ruleB = &lt;tt&gt;Branch&lt;/tt&gt; rule &lt;tt&gt;Leaf&lt;/tt&gt; &lt;tt&gt;Leaf&lt;/tt&gt;&lt;br /&gt;&gt;           &lt;kbd&gt;in&lt;/kbd&gt;  &lt;tt&gt;Zip&lt;/tt&gt; hist (mutate dir ruleB branch)&lt;/pre&gt;&lt;/blockquote&gt;The above functions are the meat of the implementation for this simple RDR system.  There are a few conveniences that the following functions provide.  The first one is &lt;code&gt;answer&lt;/code&gt; that scans the rule tree, making the best conclusion, and then backs up one step to provide the user access to the branch in case the precipitating rule finding wasn't exactly giving the desired result.&lt;blockquote&gt;&lt;pre&gt;&gt; answer :: &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v &amp;rarr; &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v&lt;br /&gt;&gt; answer rule = &lt;kbd&gt;let&lt;/kbd&gt; &lt;tt&gt;RuleEnv&lt;/tt&gt; z ans = execState runRule rule&lt;br /&gt;&gt;               &lt;kbd&gt;in&lt;/kbd&gt;  &lt;tt&gt;RuleEnv&lt;/tt&gt; (fromJust $ withdraw z) ans&lt;/pre&gt;&lt;/blockquote&gt;The next three functions help to automate the creation of the rule parts, &lt;tt&gt;Condition&lt;/tt&gt;s and &lt;tt&gt;Conclusion&lt;/tt&gt;s.  The function &lt;code&gt;mkCond&lt;/code&gt; creates a test function with the assumption that the knowledge store contains a &lt;code&gt;(k,v)&lt;/code&gt; pair.  It does the lookup in the knowledge store and passes the extracted values to the test function (which, as with any good predicate, returns either &lt;tt&gt;True&lt;/tt&gt; or &lt;tt&gt;False&lt;/tt&gt;).  If we can't find the key, I guess, for now, we'll assume the returned value is &lt;tt&gt;False&lt;/tt&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; mkCond :: &lt;tt&gt;Ord&lt;/tt&gt; k &amp;rArr; k &amp;rarr; (v &amp;rarr; &lt;tt&gt;Bool&lt;/tt&gt;) &amp;rarr; &lt;tt&gt;Condition&lt;/tt&gt; k (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt; mkCond key fn = &lt;tt&gt;Cond&lt;/tt&gt; key $ &amp;lambda; ks . &lt;kbd&gt;maybe&lt;/kbd&gt; &lt;tt&gt;False&lt;/tt&gt; fn (&lt;tt&gt;Map&lt;/tt&gt;.lookup key ks)&lt;br /&gt;&lt;br /&gt;&gt; present :: &lt;tt&gt;Ord&lt;/tt&gt; k &amp;rArr; k &amp;rarr; &lt;tt&gt;Condition&lt;/tt&gt; k (&lt;tt&gt;Knowledge&lt;/tt&gt; k v)&lt;br /&gt;&gt; present = &lt;kbd&gt;flip&lt;/kbd&gt; mkCond (&lt;kbd&gt;const&lt;/kbd&gt; &lt;tt&gt;True&lt;/tt&gt;)&lt;br /&gt;&lt;br /&gt;&gt; assume :: k &amp;rarr; &lt;tt&gt;Conclusion&lt;/tt&gt; k k env&lt;br /&gt;&gt; assume key = &lt;tt&gt;Concl&lt;/tt&gt; key (&lt;kbd&gt;const&lt;/kbd&gt; key)&lt;/pre&gt;&lt;/blockquote&gt;This completes the implementation of this RDR system.  The next entry will create a small RDR system, based on the game Animal, to demonstrate how the system works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-6703121488885077319?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/6703121488885077319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=6703121488885077319' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6703121488885077319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6703121488885077319'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/animal-as-rdr-part-ii.html' title='Animal as RDR, part II'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-7818666076778596755</id><published>2008-09-18T18:29:00.000-07:00</published><updated>2008-09-30T05:45:21.104-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='knowledge engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><title type='text'>Animal: an RDR implementation study, part I: types</title><content type='html'>&lt;strong&gt;Synopsis&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://www.cse.unsw.edu.au/~cs9416/06s1/lectures/rdr/RDR_links.html'&gt;Ripple-down rules&lt;/a&gt; provide a fast and efficient representation of &lt;em&gt;knowledge in context&lt;/em&gt; for use, e.g., by expert systems.  We present here a complete implementation of one type of RDR system in Haskell.  But what analogy is sufficient to describe what an RDR system &lt;em&gt;is&lt;/em&gt;?  The literature, albeit comprehensive, seems to concentrate more on the details of making such a system work, but none have presented the &lt;em&gt;essence&lt;/em&gt;: the computer guessing-game &lt;a href='http://www.animalgame.com/play/faq.php'&gt;Animal&lt;/a&gt; does a good job of this illustration, and we use it here to build an example knowledge base for this RDR system.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Motivation/Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As a knowledge engineer I have worked with Subject-Matter Experts (SMEs) to build various rule-based expert systems.  A common pitfall of such systems, its &lt;a href='http://en.wikipedia.org/wiki/Hubris'&gt;ὕβρις&lt;/a&gt;, is that they attempt to abstract decision making from any context.  And, as such, fail to notice the nuances or have the situational awareness needed to render useful judgments.  In a knowledge-engineered rule-based/bayesian-like hybrid system I developed, the bayesian decisions lead to over 99% of the positive findings in the transactions analyzed.&lt;br /&gt;&lt;br /&gt;This would be the end of the story if there were no hard limits, but there are always such hard limits.  Bayesian-like systems tend to scorn the advice and guidance of SMEs: the &lt;em&gt;data set itself is&lt;/em&gt; the experts, not the SMEs.  Despite the success of using the data, bayesian-like systems also tend to overreact &amp;mdash; only 1 transaction out of 1000 transactions it flagged actually lead to a decision &amp;mdash; these systems need serious throttling to be successful.  Resources, then, are a real-world constraints that rule-based systems better model than bayesian systems in practice.  In fact, hard constraints in general are modeled much better by rule-based systems.  &lt;br /&gt;&lt;br /&gt;But the rule-based systems, popularized by, e.g., iLog JRules&amp;trade; and used in many expert systems, do not speak the language of the SMEs.  Having worked with SMEs across the U.S.A. over a period of years, rules invariably tend to be defined &lt;em&gt;by exception&lt;/em&gt;.  Whenever we, as the knowledge-engineers, attempt to nail down a definition with the SMEs, the conversations always proceed as follows:&lt;blockquote&gt;SME: Yeah, a CC transaction of over $57.38 is always suspect.&lt;br /&gt;Me: So, we'll flag those, then [thinking: &lt;em&gt;Ha! that was an easy rule; finally!&lt;/em&gt;]&lt;br /&gt;SME: No, no, no! Only from young males or senior citizens in the following three income brackets.&lt;br /&gt;Me: Oh, okay, I'll add that to the constraint.&lt;br /&gt;SME: No, but it needs to be in the following zip-codes ...&lt;/blockquote&gt;Several hours later we're still ironing out the rule, and then, as lunch break approaches, the chair either tables the rule or passes a simplified, useless, version of it.&lt;br /&gt;&lt;br /&gt;Note how the rule set was defined above, the SMEs agreed to a general case, and then continue to refine that definition by adding (often conflicting) constraints.  In a context-free rule-based system, modelling such a rule set is by no means impossible, but the task quickly becomes a chore in the nightmare of complexity.&lt;br /&gt;&lt;br /&gt;RDRs (Ripple-down Rules), on the other hand, embrace the context.  The syntax of an RDR system is as follows:&lt;blockquote&gt;&lt;pre&gt;&amp;lt;rule&gt; ::= IF &lt;em&gt;condition&lt;/em&gt; THEN &lt;em&gt;conclusion&lt;/em&gt;&lt;br /&gt;&amp;lt;knowledge base&gt; ::= &amp;perp;&lt;br /&gt;                   | &amp;lt;rule&gt; &lt;br /&gt;                     EXCEPT &amp;lt;knowledge base&gt;&lt;br /&gt;                     ELSE   &amp;lt;knowledge base&gt;&lt;/pre&gt;&lt;/blockquote&gt;The semantics is as follows.  If the &lt;em&gt;condition&lt;/em&gt; is met, then that &lt;em&gt;conclusion&lt;/em&gt; is saved as a viable result (replacing any prior &lt;em&gt;conclusion&lt;/em&gt;) and the &lt;code&gt;EXCEPT&lt;/code&gt; branch is followed recursively until &lt;code&gt;&amp;perp;&lt;/code&gt;, at which time the most recently saved &lt;em&gt;conclusion&lt;/em&gt; is the result.  On the other hand, if &lt;em&gt;condition&lt;/em&gt; fails, the &lt;code&gt;ELSE&lt;/code&gt; branch is selected and followed recursively.  Of course, the knowledge base must be applied to something.  In this system, we have a very simple environment where the &lt;em&gt;condition&lt;/em&gt; tests for the presence of a &lt;tt&gt;String&lt;/tt&gt; in that environment.&lt;br /&gt;&lt;br /&gt;The initial knowledge base for every RDR system starts as:&lt;blockquote&gt;&lt;code&gt;IF (&lt;kbd&gt;const&lt;/kbd&gt; &lt;tt&gt;True&lt;/tt&gt;) THEN none EXCEPT &amp;perp; ELSE &amp;perp;&lt;/code&gt;&lt;/blockquote&gt;As the SMEs interact with the RDR system, they add to knowledge to refine the &lt;em&gt;conclusion&lt;/em&gt;s guided by refinements in the &lt;em&gt;condition&lt;/em&gt;s.  The system is very permissive, redundancy is permitted, even encouraged, because a &lt;em&gt;condition&lt;/em&gt; in depth of one path of &lt;code&gt;EXCEPT&lt;/code&gt;s and &lt;code&gt;ELSE&lt;/code&gt;s has a very different meaning, &lt;em&gt;in context&lt;/em&gt;, than along another path.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Our RDR system with be the Animal guessing game with the following knowledge base:&lt;blockquote&gt;&lt;pre&gt;IF (&lt;kbd&gt;const&lt;/kbd&gt; &lt;tt&gt;True&lt;/tt&gt;) THEN "not an animal"&lt;br /&gt;  EXCEPT IF (present "four legs") THEN "pony"&lt;br /&gt;         EXCEPT IF (present "barks") THEN "dog"&lt;br /&gt;                EXCEPT &amp;perp;&lt;br /&gt;                ELSE IF (present "meows") THEN "cat"&lt;br /&gt;                     EXCEPT &amp;perp;&lt;br /&gt;                     ELSE &amp;perp;&lt;br /&gt;         ELSE IF (present "swims") THEN "fish"&lt;br /&gt;              EXCEPT &amp;perp;&lt;br /&gt;              ELSE IF (present "spins web") THEN "spider"&lt;br /&gt;                   EXCEPT &amp;perp;&lt;br /&gt;                   ELSE &amp;perp;&lt;br /&gt;  ELSE &amp;perp;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Types&lt;/strong&gt;&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;RDRTypes&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;.&lt;tt&gt;State&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Map&lt;/tt&gt; (&lt;tt&gt;Map&lt;/tt&gt;)&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; qualified &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Map&lt;/tt&gt; as &lt;tt&gt;Map&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;I must apologize for not introducing the next three modules properly.  These modules are part of my canon and will be introduced in depth elsewhere.  For now, I must settle for the following descriptions:&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Transitive&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;defines a generic protocol of walking a data structure one step at a time, either "forward" (with &lt;code&gt;advance&lt;/code&gt;) or backward (with &lt;code&gt;withdraw&lt;/code&gt;).&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Zipper&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;The "simple Ariadne zipper" illustrated in the &lt;a href='http://en.wikibooks.org/wiki/Haskell/Zippers'&gt;Haskell Wikibooks&lt;/a&gt;.&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;BinaryTree&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;The only novel structure here is that the tree is shaped to conform to the structure of RDRs: the data is in the branch, not the leaves.&lt;blockquote&gt;From Predicate Logic-based Incremental KA, Barry Drake and Ghassan Beydoun (Nov 2000), file named PRDR.pdf&lt;br /&gt;&lt;br /&gt;2.1. Ripple Down Rules (RDR)&lt;br /&gt;An RDR knowledge base is a collection of simple rules organised in a binary tree structure. Each rule has the form, "If condition then conclusion".  Every rule can have two branches to other rules: a false-branch (also called the “or” branch) and a true-branch (also called the “exception” branch). An example RDR tree is shown in figure 2.1. When a rule is satisfied, the true branch is taken, otherwise a false branch is taken. The root node of an RDR tree contains the default rule whose condition is always satisfied, that is, it is of the form, “If true then default conclusion”. This default rule has only a true-branch.&lt;/blockquote&gt;The RDR &lt;code&gt;IF-THEN&lt;/code&gt; rule contains a &lt;em&gt;condition&lt;/em&gt; and &lt;em&gt;conclusion&lt;/em&gt; that interact with the &lt;tt&gt;Environment&lt;/tt&gt; (defined later) to inform the decision of the system.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Condition&lt;/tt&gt; a env = &lt;tt&gt;Cond&lt;/tt&gt; a (env &amp;rarr; &lt;tt&gt;Bool&lt;/tt&gt;)&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Show&lt;/tt&gt; a &amp;rArr; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;Condition&lt;/tt&gt; a env) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Cond&lt;/tt&gt; c _) = "IF " ++ &lt;kbd&gt;show&lt;/kbd&gt; c&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Conclusion&lt;/tt&gt; a b env = &lt;tt&gt;Concl&lt;/tt&gt; a (env &amp;rarr; b)&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Show&lt;/tt&gt; a &amp;rArr; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;Conclusion&lt;/tt&gt; a b env) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (Concl c _) = "THEN " ++ &lt;kbd&gt;show&lt;/kbd&gt; c&lt;/pre&gt;&lt;/blockquote&gt;Given the above, an &lt;code&gt;IF-THEN&lt;/code&gt; &lt;tt&gt;Rule&lt;/tt&gt; is simply the conjunction of the the &lt;tt&gt;Condition&lt;/tt&gt; and &lt;tt&gt;Conclusion&lt;/tt&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Rule&lt;/tt&gt; a b c kb&lt;br /&gt;&gt;      = &lt;tt&gt;Rule&lt;/tt&gt; (&lt;tt&gt;Condition&lt;/tt&gt; a kb) (&lt;tt&gt;Conclusion&lt;/tt&gt; b c kb)&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; (&lt;tt&gt;Show&lt;/tt&gt; a, &lt;tt&gt;Show&lt;/tt&gt; b) &amp;rArr; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;Rule&lt;/tt&gt; a b c kb) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Rule&lt;/tt&gt; a b) = &lt;kbd&gt;show&lt;/kbd&gt; a ++ " " ++ &lt;kbd&gt;show&lt;/kbd&gt; b&lt;/pre&gt;&lt;/blockquote&gt;The Environment is composed of a dictionary (keys to values) and the current most valid conclusion under consideration.  In our example (Animal), we merely test for the existence of a key, but more complex system usually treat the keys as attributed values and perform more than simple existence-check tests.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Knowledge&lt;/tt&gt; k v = &lt;tt&gt;Map&lt;/tt&gt; k v&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Environment&lt;/tt&gt; k v a b&lt;br /&gt;&gt;    = &lt;tt&gt;Env&lt;/tt&gt; (&lt;tt&gt;Knowledge&lt;/tt&gt; k v) (&lt;tt&gt;Conclusion&lt;/tt&gt; a b (&lt;tt&gt;Knowledge&lt;/tt&gt; k v))&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; (&lt;tt&gt;Show&lt;/tt&gt; k, &lt;tt&gt;Show&lt;/tt&gt; v, &lt;tt&gt;Show&lt;/tt&gt; a)&lt;br /&gt;&gt;          &amp;rArr; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;Environment&lt;/tt&gt; k v a b) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Env&lt;/tt&gt; kv conc) = "{" ++ &lt;kbd&gt;show&lt;/kbd&gt; kv ++ ": "&lt;br /&gt;&gt;                             ++ &lt;kbd&gt;show&lt;/kbd&gt; conc ++ "}"&lt;/pre&gt;&lt;/blockquote&gt;The above elements are what comprise the simple types for the RDR system, so what is left is those elements that form the structure.  This system is in the shape of a binary tree, so, of course, we use that data structure.  As we append new rule branches to leaves of the tree, we use the Zipper data type to allow us to add these nodes in place.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;RuleBranch&lt;/tt&gt; a b c k v&lt;br /&gt;&gt;      = &lt;tt&gt;BinaryTree&lt;/tt&gt; (&lt;tt&gt;Rule&lt;/tt&gt; a b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v))&lt;br /&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v&lt;br /&gt;&gt;      = &lt;tt&gt;Zipper BinDir&lt;/tt&gt; (&lt;tt&gt;RuleBranch&lt;/tt&gt; a b c k v)&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v = &lt;tt&gt;RuleEnv&lt;/tt&gt; (&lt;tt&gt;RuleTree&lt;/tt&gt; a b c k v)&lt;br /&gt;&gt;                                      (&lt;tt&gt;Environment&lt;/tt&gt; k v b c)&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; (&lt;tt&gt;Show&lt;/tt&gt; a, &lt;tt&gt;Show&lt;/tt&gt; b, &lt;tt&gt;Show&lt;/tt&gt; k, &lt;tt&gt;Show&lt;/tt&gt; v)&lt;br /&gt;&gt;          =&gt; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;RuleEnv&lt;/tt&gt; tree env) = "| " ++ &lt;kbd&gt;show&lt;/kbd&gt; tree ++ " : "&lt;br /&gt;&gt;                                   ++ &lt;kbd&gt;show&lt;/kbd&gt; env ++ " |"&lt;/pre&gt;&lt;/blockquote&gt;The RDR system is built around the concept of context, and the &lt;tt&gt;State Monad&lt;/tt&gt; captures that concept well.  The final type is used to shuttle around the knowledge base as well as the currently viable conclusion based on the rule finding.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;RuleFinding&lt;/tt&gt; a b c k v&lt;br /&gt;&gt;      = &lt;tt&gt;State&lt;/tt&gt; (&lt;tt&gt;RuleTreeEnv&lt;/tt&gt; a b c k v)&lt;br /&gt;&gt;              (&lt;tt&gt;Conclusion&lt;/tt&gt; b c (&lt;tt&gt;Knowledge&lt;/tt&gt; k v))&lt;/pre&gt;&lt;/blockquote&gt;The above types describe the RDR system.  In the &lt;a href='http://logicaltypes.blogspot.com/2008/09/animal-as-rdr-part-ii.html'&gt;next entry&lt;/a&gt;, we will show the implementation of the system when it comes to building and adding rules as well as traversing the rule tree to reach a conclusion.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-7818666076778596755?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/7818666076778596755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=7818666076778596755' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7818666076778596755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7818666076778596755'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/animal-rdr-implementation-study.html' title='Animal: an RDR implementation study, part I: types'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-3050519809023427745</id><published>2008-09-10T15:01:00.000-07:00</published><updated>2008-09-13T06:06:58.563-07:00</updated><title type='text'>What is declarative programming?</title><content type='html'>The concept has been bandied about, and has entered into more popular discussion with the broad acceptance of XML.  Beside the overall definition, however ("Declarative is the 'what' of programming; imperative, the 'how'"), I haven't heard a definition that sketches, even, what declarative programming is and how it looks like.&lt;br /&gt;&lt;br /&gt;For the "quartet of programming styles", being: imperative, object-oriented, functional, and logical, it seems pretty clear that there are well-defined general boundaries (with enough wiggle room to cause fanatics to enjoy flame-wars as the mood struck them) to separate one style from another, with languages easily falling into one or more of those camps:&lt;ul&gt;&lt;li&gt;C: imperative&lt;/li&gt;&lt;li&gt;Smalltalk/Java: imperative/object-oriented&lt;/li&gt;&lt;li&gt;Lisp(and Scheme and Dylan and ...)/Haskell/ML: functional&lt;/li&gt;&lt;li&gt;Prolog (Mercury): logical&lt;/li&gt;&lt;/ul&gt;This was all clear-cut and well and good.&lt;br /&gt;&lt;br /&gt;But for classifying something as "declarative programming" it seemed that there has been talk of its benefits or drawbacks, but not much more than superficial talk of what it is.  Camps from both the functional programming community and the logic programming community stake claims over the declarativeness of their programming languages, but how does one recognize code as declarative?  What is the measure by which the "declarativeness" of such code may be ascertained?&lt;br /&gt;&lt;br /&gt;Up until recently, I have been troubled by such misgivings only marginally.  I had it from authority, a Lisp giant, Patrick Winston, in a Prolog book (Bratko's 3rd ed of "Prolog Programming for Artificial Intelligence"), that the logical style of Prolog is declarative and the functional style is not.  Before your send your flame, here's the quote:&lt;blockquote&gt;"[...] In my view, modern Lisp is the champion of these [imperative] languages, for Lisp in its Common Lisp form is enormously expressive, but how to do something is still what the Lisp programmer is allowed to be expressive about.  Prolog, on the other hand, is a language that clearly breaks away from the how-type languges, encouraging the programmer to describe situations and problems, not the detailed means by which the problems are to be solved.&lt;br /&gt;&lt;br /&gt;Consequently, an introduction to Prolog is important for all students of Computer Science, for there is no better way to see what the notion of what-type programming is all about. [...]"&lt;/blockquote&gt;I add here that I also view the bulk of Haskell in this light:  although it is possible to code declaratively in Haskell, most Haskell code I see is concern with &lt;em&gt;solving&lt;/em&gt; the problem (the "how") instead of &lt;em&gt;describing&lt;/em&gt; the problem (the "what").  Put another way, it is natural to use the functional and imperative (with monadic &lt;kbd&gt;do&lt;/kbd&gt;) styles, and it takes effort to use the logic style.&lt;br /&gt;&lt;br /&gt;That has been my prejudice until recently, but then recent correspondence with colleagues, including David F. Place, who recently had an excellent article in the Monad.Reader about Monoid, has opened this issue for reexamination.  So, I turn to you, gentle reader.  I present two very different programs below.  One written in the logic style; one, functional.  Both solve the same problem, and both authors claim their own version is definitively declarative.  I view the world through a particular lense, so I see one perspective.  But I am burning with curiosity:  do you see A) or B) as declarative, or both, or neither?  If so, how do you justify your position?&lt;br /&gt;&lt;br /&gt;A) the "logical" program approach:&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;.&lt;tt&gt;State&lt;/tt&gt;&lt;br /&gt;&lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;List&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;splits :: (&lt;tt&gt;Eq&lt;/tt&gt; a) &amp;rArr; [a] &amp;rarr; [(a, [a])]&lt;br /&gt;splits list = list &gt;&gt;= &amp;lambda;x . &lt;kbd&gt;return&lt;/kbd&gt; (x, delete x list)&lt;br /&gt;&lt;br /&gt;choose :: &lt;tt&gt;Eq&lt;/tt&gt; a &amp;rArr; &lt;tt&gt;StateT&lt;/tt&gt; [a] [] a&lt;br /&gt;choose = &lt;tt&gt;StateT&lt;/tt&gt; $ &amp;lambda;s . splits s&lt;br /&gt;&lt;br /&gt;sendmory' :: &lt;tt&gt;StateT&lt;/tt&gt; [&lt;tt&gt;Int&lt;/tt&gt;] [ ] [&lt;tt&gt;Int&lt;/tt&gt;]&lt;br /&gt;sendmory' =&lt;br /&gt;     &lt;kbd&gt;do&lt;/kbd&gt;&lt;br /&gt;       &lt;kbd&gt;let&lt;/kbd&gt; m = 1&lt;br /&gt;       &lt;kbd&gt;let&lt;/kbd&gt; o = 0&lt;br /&gt;       s &amp;larr; choose&lt;br /&gt;       guard (s &gt; 7)&lt;br /&gt;       e &amp;larr; choose&lt;br /&gt;       d &amp;larr; choose&lt;br /&gt;       y &amp;larr; choose&lt;br /&gt;       n &amp;larr; choose&lt;br /&gt;       r &amp;larr; choose&lt;br /&gt;       guard (num [s, e, n, d ] + num [m, o, r , e ]&lt;br /&gt;              &amp;equiv; num [m, o, n, e, y ])&lt;br /&gt;       &lt;kbd&gt;return&lt;/kbd&gt; [s, e, n, d , m, o, r , y ]&lt;/pre&gt;&lt;/blockquote&gt;B) the functional program approach (provided by David F. Place):&lt;blockquote&gt;&lt;pre&gt;solve input accept return&lt;br /&gt;    = solve' [] input [0..9] accept return&lt;br /&gt;&lt;br /&gt;solve' bindings [] _ accept return &lt;br /&gt;          | accept bindings = [return bindings]&lt;br /&gt;          | &lt;kbd&gt;otherwise&lt;/kbd&gt; = []&lt;br /&gt;solve' bindings ((_,g):xs) digits accept return&lt;br /&gt;          = concatMap f $ g digits&lt;br /&gt;     &lt;kbd&gt;where&lt;/kbd&gt; f n = solve' (bindings++[n]) xs&lt;br /&gt;                          (delete n digits)&lt;br /&gt;                          accept return&lt;br /&gt;&lt;br /&gt;num = foldl ((+) . (*10)) 0&lt;br /&gt;&lt;br /&gt;sendMoreMoney =&lt;br /&gt;     solve (('m', const [1]) :&lt;br /&gt;            ('o', const [0]) :&lt;br /&gt;            ('s', filter ( &gt; 7)) :&lt;br /&gt;            (zip "edynr" (repeat id)))&lt;br /&gt;       (&amp;lambda; [m,o,s,e,d,y,n,r] . num [s,e,n,d] &lt;br /&gt;                                  + num [m,o,r,e]&lt;br /&gt;                                  &amp;equiv; num [m,o,n,e,y])&lt;br /&gt;       (&amp;lambda; [m,o,s,e,d,y,n,r] . [s,e,n,d,m,o,r,y])&lt;/pre&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-3050519809023427745?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/3050519809023427745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=3050519809023427745' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/3050519809023427745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/3050519809023427745'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/what-is-declarative-programming.html' title='What is declarative programming?'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1403332398020567801</id><published>2008-09-02T17:00:00.000-07:00</published><updated>2008-09-03T18:48:16.271-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fuzzy'/><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='prolog'/><title type='text'>Fuzzy unification parser in Haskell</title><content type='html'>&lt;strong&gt;Synopsis&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is a short paper on building a scanner/parser for a fuzzy logic domain-specific language (DSL).  The system takes as input a file containing an ordered set of fuzzy statements and outputs the equivalent Prolog program.  We first briefly and informally introduce the topic of fuzzy unification.  Next we provide a Backus-Naur Form (BNF) grammar of the fuzzy DSL.  Then we provide fuzzy example statements and show their transformation into Prolog statements.  Then we present the Haskell types that represent an internal representation (IR) of the fuzzy DSL as well as the instances of &lt;tt&gt;Show&lt;/tt&gt; that output the Prolog predicates that are the executable representation of the fuzzy DSL.  Then we present the scanner/parser of the fuzzy DSL.  Finally, we translate two input fuzzy files and execute queries against the result in a Prolog listener.&lt;br /&gt;&lt;br /&gt;This document is &lt;em&gt;neither&lt;/em&gt; an introduction to Fuzzy logic or unification &lt;em&gt;nor&lt;/em&gt; a tutorial on how to build and weigh fuzzy terms.  The reader is referred to the rich library of online and offline publications on these topics.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The standard execution of unification in Prolog for ground atoms is that two atoms must be of the same type and then of the same value in order to unify.  This rigor is very good for proof of program correctness and where there is no room for tolerances; in short, for classic predicate logic proofs, unification does what we need it to do.  However, standard unification hinders more than helps in the presence of real-world, messy, data or where some generality is needed in, e.g., the decision-making process of an expert system.&lt;br /&gt;&lt;br /&gt;One approach that provides some tolerance and generality in the face of messy data is to introduce fuzziness into the unification process.  In this way, we may state facts with some degree of associated certainty.  We may also embed in the rule-finding process fuzzy techniques.  Three such techniques in fuzzy rule-finding include:&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Product logic&lt;/strong&gt;, where &lt;code&gt;and_prod (x, y) = x * y&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Gödel intuitionistic logic&lt;/strong&gt;, where &lt;code&gt;and_godel (x, y) = &lt;kbd&gt;min&lt;/kbd&gt; x y&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Lukasiewicz logic&lt;/strong&gt;, where &lt;code&gt;and_luka (x, y) = &lt;kbd&gt;max&lt;/kbd&gt; 0 (x + y - 1)&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;These techniques are &lt;em&gt;conjunctive&lt;/em&gt; and are implemented in the Prolog file named prelude.pl as follows:&lt;blockquote&gt;&lt;pre&gt;and_prod(X,Y,Z) :- Z is X * Y.&lt;br /&gt;and_godel(X,Y,Z) :- min(X, Y, Z).&lt;br /&gt;and_luka(X,Y,Z) :- H is X+Y-1, max(0, H, Z).&lt;/pre&gt;&lt;/blockquote&gt;The fuzzy DSL also allows &lt;em&gt;disjunctions&lt;/em&gt; of the above.  Their implementation can also be found in prelude.pl:&lt;blockquote&gt;&lt;pre&gt;or_prod(X,Y,Z) :- Z is X + Y - (X * Y).&lt;br /&gt;or_godel(X,Y,Z) :- max(X, Y, Z).&lt;br /&gt;or_luka(X,Y,Z) :- H is X+Y, max(1, H, Z).&lt;/pre&gt;&lt;/blockquote&gt;These logics, along with the stated degree of certainty or confidence in the rule or fact, allow us to model our problem by constructing fuzzy statements.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Grammar&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;A &lt;code&gt;&amp;lt;program&gt;&lt;/code&gt; in the fuzzy DSL this scanner/parser supports is as follows:&lt;blockquote&gt;&lt;pre&gt;&amp;lt;program&gt; = &amp;lt;statement&gt;&lt;sup&gt;+&lt;/sup&gt;&lt;br /&gt;&amp;lt;statement&gt; ::= (&amp;lt;rule&gt; | &amp;lt;fact&gt;) &amp;lt;ss&gt; "with" &amp;lt;ss&gt; &amp;lt;float&gt; ".\n"&lt;br /&gt;&amp;lt;float&gt; ::= &lt;tt&gt;Float&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;fact&gt; ::= &amp;lt;term&gt;&lt;br /&gt;&amp;lt;rule&gt; ::= &amp;lt;term&gt; &amp;lt;ss&gt; &amp;lt;implication&gt; &amp;lt;ss&gt; &amp;lt;entailment&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;term&gt; ::= &amp;lt;name&gt; "(" &amp;lt;arguments&gt; ")" | &amp;lt;name&gt;&lt;br /&gt;&amp;lt;name&gt; ::= &lt;tt&gt;String&lt;/tt&gt;&lt;small&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;arguments&gt; ::= &amp;lt;argument&gt; &amp;lt;opt-args&gt;&lt;br /&gt;&amp;lt;opt-args&gt; ::= "," &amp;lt;arguments&gt; | &amp;epsilon;&lt;br /&gt;&lt;br /&gt;&amp;lt;argument&gt; ::= &amp;lt;atom&gt; | &amp;lt;variable&gt; | &amp;lt;float&gt; | &amp;lt;string&gt;&lt;br /&gt;&amp;lt;string&gt; ::= "\"" &lt;tt&gt;String&lt;/tt&gt; "\""&lt;br /&gt;&amp;lt;variable&gt; ::= &lt;tt&gt;String&lt;/tt&gt;&lt;small&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/small&gt;&lt;br /&gt;&amp;lt;atom&gt; ::= &amp;lt;name&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;implication&gt; ::= "&amp;lt;" &amp;lt;kind&gt;&lt;br /&gt;&amp;lt;kind&gt; ::= "prod" | "luka" | "godel"&lt;br /&gt;&lt;br /&gt;&amp;lt;entailment&gt; ::= &amp;lt;term&gt; &amp;lt;connector&gt; &amp;lt;term&gt; | &amp;lt;term&gt;&lt;br /&gt;&amp;lt;connector&gt; ::= &amp;lt;conjunction&gt; | &amp;lt;disjunction&gt;&lt;br /&gt;&amp;lt;conjunction&gt; ::= "&amp;amp;" &amp;lt;kind&gt;&lt;br /&gt;&amp;lt;disjunction&gt; ::= "|" &amp;lt;kind&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;ss&gt; ::= " " &amp;lt;opt-ss&gt;&lt;br /&gt;&amp;lt;opt-ss&gt; ::= &amp;lt;ss&gt; | &amp;epsilon;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;small&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/small&gt;  &lt;em&gt;no spaces, first character lowercase alpha, rest underscores and alphanums&lt;/em&gt;&lt;br /&gt;&lt;small&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/small&gt; &lt;em&gt;no spaces, first character is "_" or upcase alpha&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Transformation&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;An example of a statement of fact in the fuzzy DSL is as follows:&lt;blockquote&gt;&lt;code&gt;r(a) with 0.8.&lt;/code&gt;&lt;/blockquote&gt;An example of a rule statement is:&lt;blockquote&gt;&lt;code&gt;p(X) &amp;lt;prod q(X) &amp;amp;godel r(X) with 0.7.&lt;/code&gt;&lt;/blockquote&gt;A fuzzy statement is transformed rather directly into a Prolog statement by threading the fuzziness of the statement through the Prolog terms of the statement.  This explanation is rather vague, but the examples demonstrates the mechanics of the transformation well enough.  The fuzzy statement of fact is transformed into the following Prolog statement:&lt;blockquote&gt;&lt;code&gt;r(a, 0.8).&lt;/code&gt;&lt;/blockquote&gt;The fuzzy rule statement requires quite a bit more threading, and the system uses a chaining of logic variables to affect this:&lt;blockquote&gt;&lt;pre&gt;p(X, Certainty) :-&lt;br /&gt;    q(X, _TV1), r(X, _TV2), and_godel(_TV1, _TV2, _TV3),&lt;br /&gt;    and_prod(0.7, _TV3, Certainty).&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Strategy&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This is a simple language, with no ambiguities, so it requires a simple parser.  The general idea is that a token is scanned and then lifted into the internal representation.  This happens operationally under the aegis of the &lt;tt&gt;Maybe Monad&lt;/tt&gt; to control the flow of the parser: The system returns a &lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;foo&lt;/code&gt; when parsing succeeds and a &lt;tt&gt;Nothing&lt;/tt&gt; when the scanner/parser encounters something unexpected.  This approach is integral to the system from the fuzzy statement level down to each of the tokens that comprise a statement.  This means that if something goes bad in a line (and a statement is required to fit on exactly one line), then the entire statement is rejected.  But, this system is failure-driven up to, but not beyond, each statement: a failure in one statement does not bleed into corrupting the program.  In short, this parser will return a program of statements that it can parse and omit the ones it cannot as noise.&lt;br /&gt;&lt;br /&gt;A fuzzy logic program file is scanned and parsed into a list of fuzzy statements (&lt;code&gt;[&lt;tt&gt;Statement&lt;/tt&gt;]&lt;/code&gt;) and the corresponding &lt;kbd&gt;show&lt;/kbd&gt; functions output the internal representation as transformed Prolog predicates that can be loaded and queried in a Prolog listener.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Haskell Types&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The Haskell types that form the internal representation of a fuzzy program follow the BNF rather closely (recall the technique of &lt;a href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-i-lifting-functions.html'&gt;parsing via lifting functions&lt;/a&gt;; this module uses that technique):&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;FuzzyTypes&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Arrow&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Term&lt;/tt&gt; = &lt;tt&gt;Term String&lt;/tt&gt; [&lt;tt&gt;Arg&lt;/tt&gt;]&lt;br /&gt;&lt;br /&gt;A term requires no transformation from fuzzy DSL to Prolog:&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Term&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Term&lt;/tt&gt; name []) = name&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Term&lt;/tt&gt; name (arg:args)) = name ++ "(" ++ &lt;kbd&gt;show&lt;/kbd&gt; arg ++ show1 args ++ ")"&lt;br /&gt;&gt;        where show1 [] = ""&lt;br /&gt;&gt;              show1 (h:t) = ", " ++ &lt;kbd&gt;show&lt;/kbd&gt; h ++ show1 t&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Arg&lt;/tt&gt; = &lt;tt&gt;Atom String&lt;/tt&gt; | &lt;tt&gt;Num Float&lt;/tt&gt; | &lt;tt&gt;Str String&lt;/tt&gt; | &lt;tt&gt;Var String&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Arg&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Num&lt;/tt&gt; num) = &lt;kbd&gt;show&lt;/kbd&gt; num&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Str&lt;/tt&gt; string) = &lt;kbd&gt;show&lt;/kbd&gt; string&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Atom&lt;/tt&gt; atom) = atom&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Var&lt;/tt&gt; name) = name&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Kind&lt;/tt&gt; = &lt;tt&gt;Prod&lt;/tt&gt; | &lt;tt&gt;Luka&lt;/tt&gt; | &lt;tt&gt;Godel&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Kind&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Prod&lt;/tt&gt; =  "prod"&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Luka&lt;/tt&gt; =  "luka"&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Godel&lt;/tt&gt; = "godel"&lt;/pre&gt;&lt;/blockquote&gt;The following lifting function converts an input string to the scanner to the correct connective-type value.&lt;blockquote&gt;&lt;pre&gt;&gt; liftKind :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Kind&lt;/tt&gt;&lt;br /&gt;&gt; liftKind "prod"  = &lt;tt&gt;Just Prod&lt;/tt&gt;&lt;br /&gt;&gt; liftKind "luka"  = &lt;tt&gt;Just Luka&lt;/tt&gt;&lt;br /&gt;&gt; liftKind "godel" = &lt;tt&gt;Just Godel&lt;/tt&gt;&lt;br /&gt;&gt; liftKind _       = &lt;tt&gt;Nothing&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Implication&lt;/tt&gt; = &lt;tt&gt;Impl Kind&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;We don't have a Show instance for Implication because we need to weave in the thread of fuzziness from the consequence and entailment. So, we do the showing from the Rule perspective.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Entailment&lt;/tt&gt; = &lt;tt&gt;Goal Term&lt;/tt&gt;&lt;br /&gt;&gt;                   | &lt;tt&gt;Conjoin Kind Term Term&lt;/tt&gt;&lt;br /&gt;&gt;                   | &lt;tt&gt;Disjoin Kind Term Term&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; display :: &lt;tt&gt;Entailment&lt;/tt&gt; &amp;rarr; (&lt;tt&gt;String&lt;/tt&gt;, &lt;tt&gt;Arg&lt;/tt&gt;)&lt;br /&gt;&gt; display (&lt;tt&gt;Goal&lt;/tt&gt; term) = (&lt;kbd&gt;show&lt;/kbd&gt; . addArg term &amp;&amp;&amp; &lt;kbd&gt;id&lt;/kbd&gt;) (&lt;tt&gt;Var&lt;/tt&gt; "_TV1")&lt;br /&gt;&gt; display (&lt;tt&gt;Conjoin&lt;/tt&gt; kind a b) = (showConnection "and" kind a b, &lt;tt&gt;Var&lt;/tt&gt; "_TV3")&lt;br /&gt;&gt; display (&lt;tt&gt;Disjoin&lt;/tt&gt; kind a b) = (showConnection "or" kind a b, &lt;tt&gt;Var&lt;/tt&gt; "_TV3")&lt;br /&gt;&lt;br /&gt;&gt; showConnection :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Kind&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt;&lt;br /&gt;&gt; showConnection conj kind a b =&lt;br /&gt;&gt;       &lt;kbd&gt;show&lt;/kbd&gt; (addArg a (&lt;tt&gt;Var&lt;/tt&gt; "_TV1")) ++ ", "&lt;br /&gt;&gt;            ++ &lt;kbd&gt;show&lt;/kbd&gt; (addArg b (&lt;tt&gt;Var&lt;/tt&gt; "_TV2")) ++ ", "&lt;br /&gt;&gt;            ++ &lt;kbd&gt;show&lt;/kbd&gt; (mkTerm conj kind (&lt;kbd&gt;map&lt;/kbd&gt; anon [1..3]))&lt;br /&gt;&lt;br /&gt;&gt; mkConnection :: &lt;tt&gt;Char&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Kind&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Entailment&lt;/tt&gt;&lt;br /&gt;&gt; mkConnection conn kind t0 t1 | conn &amp;ne; '|'  = &lt;tt&gt;Just&lt;/tt&gt; $ &lt;tt&gt;Disjoin&lt;/tt&gt; kind t0 t1&lt;br /&gt;&gt;                              | conn &amp;ne; '&amp;'  = &lt;tt&gt;Just&lt;/tt&gt; $ &lt;tt&gt;Conjoin&lt;/tt&gt; kind t0 t1&lt;br /&gt;&gt;                              | &lt;kbd&gt;otherwise&lt;/kbd&gt;   = &lt;tt&gt;Nothing&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; mkTerm :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Kind&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;Arg&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt;&lt;br /&gt;&gt; mkTerm conj kind args = Term (conj ++ "_" ++ &lt;kbd&gt;show&lt;/kbd&gt; kind) args&lt;br /&gt;&lt;br /&gt;&gt; anon :: &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Arg&lt;/tt&gt;&lt;br /&gt;&gt; anon x = &lt;tt&gt;Var&lt;/tt&gt; ("_TV" ++ &lt;kbd&gt;show&lt;/kbd&gt; x)&lt;/pre&gt;&lt;/blockquote&gt;We've finally built up enough infrastructure to represent a fuzzy rule:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Rule&lt;/tt&gt; = &lt;tt&gt;Rule Term Implication Entailment Float&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;e.g.: &lt;tt&gt;Rule&lt;/tt&gt; (&lt;tt&gt;Term&lt;/tt&gt; "p" [&lt;tt&gt;Var&lt;/tt&gt; "X"]) (&lt;tt&gt;Impl Prod&lt;/tt&gt;)&lt;br /&gt;           (&lt;tt&gt;Conjoin Godel&lt;/tt&gt; (&lt;tt&gt;Term&lt;/tt&gt; "q" [&lt;tt&gt;Var&lt;/tt&gt; "X", &lt;tt&gt;Var&lt;/tt&gt; "Y"]) &lt;br /&gt;                          (&lt;tt&gt;Term&lt;/tt&gt; "r" [&lt;tt&gt;Var&lt;/tt&gt; "Y"])) 0.8&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Rule&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Rule&lt;/tt&gt; conseq (&lt;tt&gt;Impl&lt;/tt&gt; kind) preds fuzz) =&lt;br /&gt;&gt;        &lt;kbd&gt;let&lt;/kbd&gt; cert = &lt;tt&gt;Var&lt;/tt&gt; "Certainty"&lt;br /&gt;&gt;            fuzzyHead = addArg conseq cert &lt;br /&gt;&gt;            (goals, var) = display preds&lt;br /&gt;&gt;            final = mkTerm "and" kind [&lt;tt&gt;Num&lt;/tt&gt; fuzz, var, cert]&lt;br /&gt;&gt;        &lt;kbd&gt;in&lt;/kbd&gt;  &lt;kbd&gt;show&lt;/kbd&gt; fuzzyHead ++ " :- " ++ goals ++ ", " ++ &lt;kbd&gt;show&lt;/kbd&gt; final&lt;/pre&gt;&lt;/blockquote&gt;Representing and showing fuzzy facts turn out to be a rather underwhelming spectacle:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Fact&lt;/tt&gt; = &lt;tt&gt;Fact Term Float&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Fact&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Fact&lt;/tt&gt; term fuzz) = &lt;kbd&gt;show&lt;/kbd&gt; (addArg term (&lt;tt&gt;Num&lt;/tt&gt; fuzz))&lt;br /&gt;&lt;br /&gt;e.g. &lt;tt&gt;Fact&lt;/tt&gt; (&lt;tt&gt;Term&lt;/tt&gt; "r" [&lt;tt&gt;Var&lt;/tt&gt; "_"]) 0.7&lt;br /&gt;     &lt;tt&gt;Fact&lt;/tt&gt; (&lt;tt&gt;Term&lt;/tt&gt; "s" [&lt;tt&gt;Atom&lt;/tt&gt; "b"]) 0.9&lt;/pre&gt;&lt;/blockquote&gt;And an fuzzy statement is either a fuzzy rule or a fuzzy fact:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Statement&lt;/tt&gt; = &lt;tt&gt;R Rule&lt;/tt&gt; | &lt;tt&gt;F Fact&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Statement&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;R&lt;/tt&gt; rule) = &lt;kbd&gt;show&lt;/kbd&gt; rule ++ "."&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;F&lt;/tt&gt; fact) = &lt;kbd&gt;show&lt;/kbd&gt; fact ++ "."&lt;/pre&gt;&lt;/blockquote&gt;Yes, I realize the following implementation of &lt;code&gt;snoc&lt;/code&gt; ("&lt;code&gt;cons&lt;/code&gt;ing" to end of a list) is horribly inefficient, but since all the argument lists seem to be very small, I'm willing to pay the O(n&lt;sup&gt;&lt;small&gt;2&lt;/small&gt;&lt;/sup&gt;) cost.  If it becomes prohibitive, I'll swap out the term argument (proper) list with a &lt;a href='http://logicaltypes.blogspot.com/2008/08/using-difference-lists.html'&gt;difference list&lt;/a&gt;.&lt;blockquote&gt;&lt;pre&gt;&gt; snoc :: [a] &amp;rarr; a &amp;rarr; [a]&lt;br /&gt;&gt; list `snoc` elt = &lt;kbd&gt;reverse&lt;/kbd&gt; (elt : &lt;kbd&gt;reverse&lt;/kbd&gt; list)&lt;br /&gt;&lt;br /&gt;&gt; addArg :: &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Arg&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt;&lt;br /&gt;&gt; addArg (&lt;tt&gt;Term&lt;/tt&gt; t args) arg = &lt;tt&gt;Term&lt;/tt&gt; t (args `snoc` arg)&lt;/pre&gt;&lt;/blockquote&gt;&lt;strong&gt;Haskell Scanner/Parser&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The types defined above provide strong guidance for the development of the parser.  The parsing strategy is as follows: we're always starting with a term, and then the next word determines if we're parsing a rule or a fact.  A rule has the implication operators; a fact, the 'with' closure.&lt;br /&gt;&lt;br /&gt;We'll assume for now that facts and rules are all one-liners and that tokens are words (separated by spaces).  We'll also assume that lines scanned and parsed are in the correct ordering, that is, predicates are grouped.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;FuzzyParser&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Arrow&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Applicative&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;Maybe&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;FuzzyTypes&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;Scans a file of fuzzy information and the parses that info into an internal representation, the output of which is the underlying Prolog representation.  We weave in nondeterminism into the fuzzy scanner/parser by transporting the parsed result in the &lt;tt&gt;Maybe Monad&lt;/tt&gt;.  If we encounter a situation where we are unable to parse (all or part of) the &lt;tt&gt;Statement&lt;/tt&gt;, the value flips to &lt;tt&gt;Nothing&lt;/tt&gt; and bails out with &lt;kbd&gt;fail&lt;/kbd&gt;.&lt;blockquote&gt;&lt;pre&gt;&gt; parseFuzzy :: [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; [&lt;tt&gt;Statement&lt;/tt&gt;]&lt;br /&gt;&gt; parseFuzzy eaches = (mapMaybe (parseStatement . &lt;kbd&gt;words&lt;/kbd&gt;) eaches)&lt;br /&gt;&lt;br /&gt;&gt; parseStatement :: [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe Statement&lt;/tt&gt;&lt;br /&gt;&gt; parseStatement (term:rest) = &lt;kbd&gt;let&lt;/kbd&gt; t = parseTerm term&lt;br /&gt;&gt;                              &lt;kbd&gt;in  maybe&lt;/kbd&gt; (parseRule t rest &gt;&gt;= &lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;R&lt;/tt&gt;)&lt;br /&gt;&gt;                                        (&lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;F&lt;/tt&gt; . &lt;tt&gt;Fact&lt;/tt&gt; t)&lt;br /&gt;&gt;                                        (parseFuzziness rest)&lt;/pre&gt;&lt;/blockquote&gt;The &lt;tt&gt;Term&lt;/tt&gt; is a fundamental part of the fuzzy system, and is where we spend the most time scanning/parsing and hand-holding (as it has a rather huge helper function: &lt;code&gt;parseArgs&lt;/code&gt;).&lt;blockquote&gt;&lt;pre&gt;&gt; parseTerm :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Term&lt;/tt&gt;&lt;br /&gt;&gt; parseTerm word = &lt;kbd&gt;let&lt;/kbd&gt; (name, rest) = token word&lt;br /&gt;&gt;                  &lt;kbd&gt;in&lt;/kbd&gt;  &lt;tt&gt;Term&lt;/tt&gt; name (parseArgs rest)&lt;br /&gt;&lt;br /&gt;&gt; parseArgs :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;Arg&lt;/tt&gt;]&lt;br /&gt;&gt; parseArgs arglist = parseArgs' arglist&lt;br /&gt;&gt;     where parseArgs' [] = []&lt;br /&gt;&gt;           parseArgs' args@(_:_) = &lt;kbd&gt;let&lt;/kbd&gt; (anArg, rest) = token args&lt;br /&gt;&gt;                                   &lt;kbd&gt;in&lt;/kbd&gt;  parseArg anArg : parseArgs rest&lt;/pre&gt;&lt;/blockquote&gt;For parseArg we try to convert the argument to (in sequence) a number, a variable, a quoted string and then finally an atom.  The first one that succeeds is the winner.  We do this by using some &lt;code&gt;&lt;a href='http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Applicative.html'&gt;&lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Applicative&lt;/tt&gt;&lt;/a&gt;&lt;/code&gt; magic (specifically, &lt;code&gt;&amp;lt;*&gt;&lt;/code&gt; allows us to apply multiple functions (in the first list) over and over again to the argument list in the second list) followed by some monadic magic (&lt;code&gt;msum&lt;/code&gt; over &lt;tt&gt;Maybe&lt;/tt&gt; returns the first successful value (with &lt;code&gt;atomArg&lt;/code&gt;, as it always succeeds, guaranteeing that there will be at least one success), and &lt;code&gt;fromJust&lt;/code&gt; converting that &lt;tt&gt;Maybe&lt;/tt&gt; success value into a plain (non-monadic) value).&lt;blockquote&gt;&lt;pre&gt;&gt; parseArg :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Arg&lt;/tt&gt;&lt;br /&gt;&gt; parseArg arg = fromJust (msum ([numArg, varArg, strArg, atomArg] &lt;*&gt; [arg]))&lt;/pre&gt;&lt;/blockquote&gt;For the following functions recall how my "implied-by" operator (&lt;code&gt;|-&lt;/code&gt;) &lt;a href='http://logicaltypes.blogspot.com/2008/05/composing-functions-with-arrows.html'&gt;works&lt;/a&gt;: in &lt;code&gt;a&amp;nbsp;|-&amp;nbsp;b&lt;/code&gt;, &lt;code&gt;a&lt;/code&gt; is &lt;kbd&gt;return&lt;/kbd&gt;ed, given &lt;code&gt;b&lt;/code&gt; (is &lt;tt&gt;True&lt;/tt&gt;).  Given that, the below functions attempt to convert the scanned argument into a parsed (typed) one: a number, a (logic) variable, a string, or an atom:&lt;blockquote&gt;&lt;pre&gt;Here's how we try to convert an argument ...&lt;br /&gt;&lt;br /&gt;First we try to see if it's a number&lt;br /&gt;&lt;br /&gt;&gt; numArg :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Arg&lt;/tt&gt;&lt;br /&gt;&gt; numArg x = &lt;tt&gt;Num&lt;/tt&gt; (&lt;kbd&gt;read&lt;/kbd&gt; x) |- &lt;kbd&gt;all&lt;/kbd&gt; (&lt;kbd&gt;flip elem&lt;/kbd&gt; ('.' : ['0' .. '9'])) x&lt;br /&gt;&lt;br /&gt;Next, is it a (n anonymous) variable?&lt;br /&gt;&lt;br /&gt;&gt; varArg :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Arg&lt;/tt&gt;&lt;br /&gt;&gt; varArg x@(h:_) = &lt;tt&gt;Var&lt;/tt&gt; x |- (h == '_' || h `&lt;kbd&gt;elem&lt;/kbd&gt;` ['A' .. 'Z'])&lt;br /&gt;&lt;br /&gt;Maybe it's a string?&lt;br /&gt;&lt;br /&gt;&gt; strArg :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Arg&lt;/tt&gt;&lt;br /&gt;&gt; strArg x@(h:t) = &lt;tt&gt;Str&lt;/tt&gt; (chop t) |- (h == '"')&lt;br /&gt;&lt;br /&gt;Okay, then, it must be an atom then&lt;br /&gt;&lt;br /&gt;&gt; atomArg :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Arg&lt;/tt&gt;&lt;br /&gt;&gt; atomArg = &lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;Atom&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;... and chop we shamelessly steal from the Perl folks.&lt;br /&gt;&lt;br /&gt;&gt; chop :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt;&lt;br /&gt;&gt; chop list = chop' [&lt;kbd&gt;head&lt;/kbd&gt; list] (&lt;kbd&gt;tail&lt;/kbd&gt; list)&lt;br /&gt;&gt;    where chop' ans rest@(h:t) | t == []   = &lt;kbd&gt;reverse&lt;/kbd&gt; ans&lt;br /&gt;&gt;                               | &lt;kbd&gt;otherwise&lt;/kbd&gt; = chop' (h:ans) t&lt;/pre&gt;&lt;/blockquote&gt;Now that we've laid the ground work, let's parse in the statements.  A statement is a fact or a rule.  Remember that &lt;code&gt;parseStatement&lt;/code&gt; parsed the first term and then branched based on whether implication followed (for a rule) or the &lt;code&gt;with&lt;/code&gt; fuzziness closed out the statement (for a fact).  So, we'll tackle parsing in a fact first; since a fact is just a term, and it's already been parsed, pretty much all we need to do now is to reify the term into the fact type:&lt;blockquote&gt;&lt;pre&gt;&gt; parseFact :: &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; &lt;tt&gt;[String]&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Fact&lt;/tt&gt;&lt;br /&gt;&gt; parseFact term fuzzes = &lt;kbd&gt;return&lt;/kbd&gt; $ &lt;tt&gt;Fact&lt;/tt&gt; term (&lt;kbd&gt;read&lt;/kbd&gt; $ chop (&lt;kbd&gt;head&lt;/kbd&gt; fuzzes))&lt;/pre&gt;&lt;/blockquote&gt;That was easy!  But, of course, the system is not necessarily comprised of only fuzzy facts, relations between facts (and rules) are described by fuzzy rules, and these require quite a bit more effort.  The general form of a rule is the &lt;em&gt;consequence&lt;/em&gt; followed by its &lt;em&gt;entailment&lt;/em&gt;.  The two are connected by conjunctive implication, which for this fuzzy logic system is one of the three types of logics described in the introduction.&lt;blockquote&gt;&lt;pre&gt;&gt; parseRule :: &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe Rule&lt;/tt&gt;&lt;br /&gt;&gt; parseRule conseq rest =&lt;br /&gt;&gt;    -- the first word is the implication type&lt;br /&gt;&gt;    parseImpl rest &gt;&gt;= &amp;lambda;(impl, r0) .&lt;br /&gt;&gt;    -- then we have a term ...&lt;br /&gt;&gt;        &lt;kbd&gt;let&lt;/kbd&gt; t0 = parseTerm $ &lt;kbd&gt;head&lt;/kbd&gt; r0&lt;br /&gt;&gt;    -- then either a connection or just the "with" closer&lt;br /&gt;&gt;        &lt;kbd&gt;in&lt;/kbd &gt; parseEntailment t0 (&lt;kbd&gt;tail&lt;/kbd&gt; r0) &gt;&gt;= &amp;lambda;(ent, fuzz) .&lt;br /&gt;&gt;           &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Rule&lt;/tt&gt; conseq impl ent fuzz)&lt;/pre&gt;&lt;/blockquote&gt;Parsing the implication is easy: we simply lift the kind of the fuzzy logic used for the implication into the &lt;tt&gt;Implication&lt;/tt&gt; data type:&lt;blockquote&gt;&lt;pre&gt;&gt; parseImpl :: [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; (&lt;tt&gt;Implication&lt;/tt&gt;, [&lt;tt&gt;String&lt;/tt&gt;])&lt;br /&gt;&gt; parseImpl (im:rest) = guard (&lt;kbd&gt;head&lt;/kbd&gt; im == '&lt;') &gt;&gt;&lt;br /&gt;&gt;                       liftKind (&lt;kbd&gt;tail&lt;/kbd&gt; im) &gt;&gt;= &amp;lambda;kind .&lt;br /&gt;&gt;                       &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Impl&lt;/tt&gt; kind, rest)&lt;/pre&gt;&lt;/blockquote&gt;Parsing entailment also turns out to be a simple task (recall my description of &lt;a href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html'&gt;how &lt;kbd&gt;maybe&lt;/kbd&gt; works&lt;/a&gt;): we parse in a term, and then we attempt to parse in a fuzzy value.  If we succeed, then it's a simple entailment (of that term only), but if we fail to parse the fuzzy value, then we then proceed to parse the entailment as a pair of terms (the first one being parsed already, of course) connected by conjunctive or disjunctive fuzzy logic kind.&lt;blockquote&gt;&lt;pre&gt;&gt; parseEntailment :: &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; (&lt;tt&gt;Entailment&lt;/tt&gt;, &lt;tt&gt;Float&lt;/tt&gt;)&lt;br /&gt;&gt; parseEntailment t rest = &lt;kbd&gt;maybe&lt;/kbd&gt; (parseConnector t rest) &lt;br /&gt;&gt;                                (&amp;lambda;fuzz . &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Goal&lt;/tt&gt; t, fuzz))&lt;br /&gt;&gt;                                (parseFuzziness rest)&lt;/pre&gt;&lt;/blockquote&gt;The parser for compound entailment is also a straightforward monadic parser: it lifts the connector into its appropriate &lt;tt&gt;Kind&lt;/tt&gt;, parses the connected &lt;tt&gt;Term&lt;/tt&gt; and then grabs the fuzzy value to complete the conjunctive or disjunctive &lt;tt&gt;Entailment&lt;/tt&gt;.&lt;blockquote&gt;&lt;pre&gt;&gt; parseConnector :: &lt;tt&gt;Term&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; (&lt;tt&gt;Entailment&lt;/tt&gt;, &lt;tt&gt;Float&lt;/tt&gt;)&lt;br /&gt;&gt; parseConnector t0 strs@(conn:rest) = liftKind (&lt;kbd&gt;tail&lt;/kbd&gt; conn) &gt;&gt;= &amp;lambda;kind .&lt;br /&gt;&gt;                                      parseFuzziness (&lt;kbd&gt;tail&lt;/kbd&gt; rest) &gt;&gt;= &amp;lambda;fuzz .&lt;br /&gt;&gt;                                      mkConnection (&lt;kbd&gt;head&lt;/kbd&gt; conn) kind t0 (parseTerm (&lt;kbd&gt;head&lt;/kbd&gt; rest)) &gt;&gt;= &amp;lambda;ent .&lt;br /&gt;&gt;                                      &lt;kbd&gt;return&lt;/kbd&gt; (ent, fuzz)&lt;/pre&gt;&lt;/blockquote&gt;Finally, &lt;code&gt;parseFuzziness&lt;/code&gt; &lt;kbd&gt;read&lt;/kbd&gt;s in the fuzzy value from the stream as a floating-point number, given that it is preceeded by "with" (as dictated by the grammar):&lt;blockquote&gt;&lt;pre&gt;&gt; parseFuzziness :: [&lt;tt&gt;String&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe Float&lt;/tt&gt;&lt;br /&gt;&gt; parseFuzziness trail = &lt;kbd&gt;read&lt;/kbd&gt; (chop (cadr trail)) |- (&lt;kbd&gt;head&lt;/kbd&gt; trail == "with")&lt;/pre&gt;&lt;/blockquote&gt;The rest of system are low-level scanning routines and helper functions:&lt;blockquote&gt;&lt;pre&gt;&gt; cadr :: [a] &amp;rarr; a&lt;br /&gt;&gt; cadr = &lt;kbd&gt;head&lt;/kbd&gt; . &lt;kbd&gt;tail&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; splitters :: &lt;tt&gt;String&lt;/tt&gt;&lt;br /&gt;&gt; splitters = "(), "&lt;br /&gt;&lt;br /&gt;&gt; token :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; (&lt;tt&gt;String&lt;/tt&gt;, &lt;tt&gt;String&lt;/tt&gt;)&lt;br /&gt;&gt; token = consumeAfter splitters&lt;br /&gt;&lt;br /&gt;&gt; consumeAfter :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; (&lt;tt&gt;String&lt;/tt&gt;, &lt;tt&gt;String&lt;/tt&gt;)&lt;br /&gt;&gt; consumeAfter _ [] = ("", "")&lt;br /&gt;&gt; consumeAfter guards (h:t) | h `&lt;kbd&gt;elem&lt;/kbd&gt;` guards = ("", t)&lt;br /&gt;&gt;                           | &lt;kbd&gt;otherwise&lt;/kbd&gt;       = &lt;a href='http://haskell.org/arrows/'&gt;first&lt;/a&gt; (h:) (consumeAfter guards t)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Running the system&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;We provide a simple &lt;code&gt;main&lt;/code&gt; function to create an executable (let's call it "fuzz") ...&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;Main&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;FuzzyParser&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; main :: &lt;tt&gt;IO&lt;/tt&gt; ()&lt;br /&gt;&gt; main = &lt;kbd&gt;do&lt;/kbd&gt; file &amp;larr; getContents&lt;br /&gt;&gt;           &lt;kbd&gt;putStrLn&lt;/kbd&gt; ":- [prelude].\n"&lt;br /&gt;&gt;           &lt;kbd&gt;mapM_&lt;/kbd&gt; (&lt;kbd&gt;putStrLn&lt;/kbd&gt; . &lt;kbd&gt;show&lt;/kbd&gt;) (parseFuzzy (&lt;kbd&gt;lines&lt;/kbd&gt; file))&lt;/pre&gt;&lt;/blockquote&gt;... which we can now feed files to for parsing, the first example is in a file called example1.flp:&lt;blockquote&gt;&lt;pre&gt;p(X) &amp;lt;prod q(X,Y) &amp;amp;godel r(Y) with 0.8.&lt;br /&gt;q(a,Y) &amp;lt;prod s(Y) with 0.7.&lt;br /&gt;q(b,Y) &amp;lt;luka r(Y) with 0.8.&lt;br /&gt;r(_) with 0.6.&lt;br /&gt;s(b) with 0.9.&lt;/pre&gt;&lt;/blockquote&gt;We run the system in the shell...&lt;blockquote&gt;&lt;code&gt;&lt;font color='black'&gt;geophf$ ./fuzz &amp;lt; example1.flp &gt; example1.pl&lt;/font&gt;&lt;/code&gt;&lt;/blockquote&gt;... obtaining the resulting logic program:&lt;blockquote&gt;&lt;pre&gt;:- [prelude].&lt;br /&gt;&lt;br /&gt;p(X, Certainty) :- q(X, Y, _TV1), r(Y, _TV2), and_godel(_TV1, _TV2, _TV3), and_prod(0.8, _TV3, Certainty).&lt;br /&gt;q(a, Y, Certainty) :- s(Y, _TV1), and_prod(0.7, _TV1, Certainty).&lt;br /&gt;q(b, Y, Certainty) :- r(Y, _TV1), and_luka(0.8, _TV1, Certainty).&lt;br /&gt;r(_, 0.6).&lt;br /&gt;s(b, 0.9).&lt;/pre&gt;&lt;/blockquote&gt;... which can be loaded into any Prolog listener, such as &lt;a href='http://www.binnetcorp.com/download/jinnidemo/index.html'&gt;Jinni&lt;/a&gt; or &lt;a href='http://www.swi-prolog.org/'&gt;SWI&lt;/a&gt;:&lt;blockquote&gt;&lt;pre&gt;&lt;font color='black'&gt;geophf$ prolog&lt;br /&gt;&lt;br /&gt;?- [example1].&lt;br /&gt;yes&lt;br /&gt;&lt;br /&gt;?- p(X, Certainty).&lt;br /&gt;X = a, Certainty = 0.48 ;&lt;br /&gt;X = b, Certainty = 0.32 ;&lt;br /&gt;no&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;Similarly, a different fuzzy system, described in the file example2.flp:&lt;blockquote&gt;&lt;pre&gt;p(X) &amp;lt;prod q(X) with 0.9.&lt;br /&gt;p(X) &amp;lt;godel r(X) with 0.8.&lt;br /&gt;q(X) &amp;lt;luka r(X) with 0.7.&lt;br /&gt;r(a) with 0.6.&lt;br /&gt;r(b) with 0.5.&lt;/pre&gt;&lt;/blockquote&gt;... results in the following Prolog file (saved as example2.pl):&lt;blockquote&gt;&lt;pre&gt;:- [prelude].&lt;br /&gt;&lt;br /&gt;p(X, Certainty) :- q(X, _TV1), and_prod(0.9, _TV1, Certainty).&lt;br /&gt;p(X, Certainty) :- r(X, _TV1), and_godel(0.8, _TV1, Certainty).&lt;br /&gt;q(X, Certainty) :- r(X, _TV1), and_luka(0.7, _TV1, Certainty).&lt;br /&gt;r(a, 0.6).&lt;br /&gt;r(b, 0.5).&lt;/pre&gt;&lt;/blockquote&gt;... and gives the following run:&lt;blockquote&gt;&lt;pre&gt;&lt;font color='black'&gt;geophf$ prolog&lt;br /&gt;&lt;br /&gt;?- [example2].&lt;br /&gt;yes&lt;br /&gt;&lt;br /&gt;?- p(X, Certainty).&lt;br /&gt;X = a, Certainty = 0.27 ;&lt;br /&gt;X = b, Certainty = 0.18 ;&lt;br /&gt;X = a, Certainty = 0.6 ;&lt;br /&gt;X = b, Certainty = 0.5 ;&lt;br /&gt;no&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;We've presented and explained a Fuzzy unification scanner/parser in Haskell and demonstrated that system producing executable Prolog code against which queries may be essayed.  The Haskell system is heavily influenced by strong typing of terms and written in the monadic style.  It is comprised of three modules, totalling less than 250 lines of code.  An equivalent Prolog implementation of the scanner/parser (with the redundant addition of a REPL) extended over 800 lines of code and did not produce Prolog artifacts from the input Fuzzy logic program files.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1403332398020567801?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1403332398020567801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1403332398020567801' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1403332398020567801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1403332398020567801'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/fuzzy-unification-parser-in-haskell.html' title='Fuzzy unification parser in Haskell'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1104451234541062591</id><published>2008-09-01T20:57:00.000-07:00</published><updated>2008-09-01T23:49:49.244-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comonad'/><title type='text'>A stream of primes as Comonad</title><content type='html'>I figured I've beaten enough around this bush to encircle it with a path half-a-meter in depth.  So, I've finally decided to bear down enough to study comonad types and to create my own instance.&lt;br /&gt;&lt;br /&gt;The above is a &lt;em&gt;caveat&lt;/em&gt;: this is an introductory guide from a beginner's perspective. YMMV.  But, perhaps, as the other material out there on comonads is rather scarce to begin with, and rather intimidating where present, this entry may spark the interest of the reader wishing to start off on comonads and doing some basic things with them.&lt;br /&gt;&lt;br /&gt;The comonad definition I use is from Edward Kmett's &lt;a href='http://comonad.com/reader/'&gt;Comonad.Reader&lt;/a&gt; category-extras &lt;a href='http://comonad.com/reader/source;item=libraries'&gt;library&lt;/a&gt;.  What a sweet library it is; &amp;perp;-trophy is in the ether-mail.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Let's talk a bit about what a comonad is, first.  A comonad is a special way at looking at a data structure that allows one to work with the individual members of that data structure in the context of the entire data structure.  It takes the opposite approach to the data in the data structure that monads do, so the monadic &lt;code&gt;bind&lt;/code&gt; (&lt;code&gt;&gt;&gt;=&lt;/code&gt;) ...&lt;blockquote&gt;&lt;code&gt;&gt;&gt;= :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m a &amp;rarr; (a &amp;rarr; m b) &amp;rarr; m b&lt;/code&gt;&lt;/blockquote&gt;... has its dual in the comonad (commonly called &lt;code&gt;cobind&lt;/code&gt;, but sensibly named &lt;code&gt;extend&lt;/code&gt; (&lt;code&gt;=&gt;&gt;&lt;/code&gt;) in &lt;code&gt;&lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Comonad&lt;/tt&gt;&lt;/code&gt;).  Its signature is as follows:&lt;blockquote&gt;&lt;code&gt;=&gt;&gt; :: &lt;tt&gt;Comonad&lt;/tt&gt; w &amp;rArr; w a &amp;rarr; (w a &amp;rarr; b) &amp;rarr; w b&lt;/code&gt;&lt;/blockquote&gt;I started gaining insight into comonads by studying the extender function &amp;mdash; it takes the comonad in its entirety and resolves that to a value in context.  That value is then used to reassemble the comonad into its new form.  In short, the extender &lt;em&gt;synthesizes&lt;/em&gt; the comonad.&lt;br /&gt;&lt;br /&gt;That's &lt;code&gt;extend&lt;/code&gt;.  Now, just as monads have the unit function (&lt;kbd&gt;return&lt;/kbd&gt;) that creates a monad from a plain value ...&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;return&lt;/kbd&gt; :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; a &amp;rarr; m a&lt;/code&gt;&lt;/blockquote&gt;... so, too, comonad has the dual of that function, called counit (or, again, more sensibly called &lt;code&gt;extract&lt;/code&gt; for the library I'm using) ...&lt;blockquote&gt;&lt;code&gt;extract :: (&lt;tt&gt;Copointed&lt;/tt&gt; f, &lt;tt&gt;Functor&lt;/tt&gt; f) &amp;rArr; f a &amp;rarr; a&lt;/code&gt;&lt;/blockquote&gt;... which, instead of injecting a value &lt;em&gt;into&lt;/em&gt; the comonad, it &lt;code&gt;extract&lt;/code&gt;s a value &lt;em&gt;from&lt;/em&gt; the comonad.&lt;br /&gt;&lt;br /&gt;That's comonad, in a nutshell: the dual of monad.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Synthesis&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Okay, then, let's jump right in to creating and using a Comonad instance.  We'll start with the list data type:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Comonad&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Arrow&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;List&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Copointed&lt;/tt&gt; [] &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;   extract = &lt;kbd&gt;head&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Comonad&lt;/tt&gt; [] &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;   extend fn [] = []&lt;br /&gt;&gt;   extend fn list@(h:t) = fn list : (t =&gt;&gt; fn)&lt;/pre&gt;&lt;/blockquote&gt;Just like for monads where &lt;code&gt;m &gt;&gt;= &lt;kbd&gt;return&lt;/kbd&gt;&lt;/code&gt; is the &lt;a href='http://logicaltypes.blogspot.com/2008/05/trivial-monad-solutions-cont.html'&gt;(right) identity&lt;/a&gt;, we can show that for comonads that &lt;code&gt;w&amp;nbsp;=&gt;&gt;&amp;nbsp;extract&lt;/code&gt; is an identity:&lt;blockquote&gt;&lt;code&gt;[1..10] =&gt;&gt; extract&lt;/code&gt;&lt;/blockquote&gt;What's the answer that you obtain? Why?&lt;br /&gt;&lt;br /&gt;Now that we can use the whole list to create each element of the new list, thanks to the Comonad protocol, let's solve the example problem from &lt;a href='http://haskell.org/haskellwiki/The_Monad.Reader/Issue4/Why_Attribute_Grammars_Matter'&gt;Why Attribute Grammars Matter&lt;/a&gt;, which is we must replace each element with the difference from the average of the list.  With comonads, that's easy to express!&lt;blockquote&gt;&lt;pre&gt;&gt; avg list = &lt;kbd&gt;sum&lt;/kbd&gt; list / genericLength list&lt;br /&gt;&gt; diff list = list =&gt;&gt; (&lt;a href='http://storytotell.org/articles/2007/04/08/haskell-arrows'&gt;extract &amp;&amp;&amp; avg &gt;&gt;&gt; &lt;kbd&gt;uncurry&lt;/kbd&gt; (-)&lt;/a&gt;)&lt;/pre&gt;&lt;/blockquote&gt;What does &lt;code&gt;diff [1..10]&lt;/code&gt; give you, and why?&lt;br /&gt;&lt;br /&gt;Now, the comonad did not eliminate the problem of multiple list traversals that Wouter points out in his article (please do read it!), but comonads do show a nice, simple, &lt;em&gt;natural&lt;/em&gt; way to synthesize the whole to build each part.  Beautiful!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;A stream ...&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Streams can be considered infinite lists, and are of the form:&lt;blockquote&gt;&lt;code&gt;a :&amp;lt; b :&amp;lt; ...&lt;/code&gt;&lt;/blockquote&gt;Uustalu and Vene, of course, discuss the &lt;tt&gt;Stream Comonad&lt;/tt&gt;, but I obtained my implementation from &lt;a href='http://www.cs.helsinki.fi/u/ekarttun/comonad/'&gt;a site with a collection of Comonad types&lt;/a&gt;, modifying to work with Kmett's protocol:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Comonad&lt;/tt&gt;.&lt;tt&gt;Stream&lt;/tt&gt; &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Comonad&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Stream&lt;/tt&gt; a = a :&amp;lt; &lt;tt&gt;Stream&lt;/tt&gt; a&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Show&lt;/tt&gt; a &amp;rArr; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;Stream&lt;/tt&gt; a) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; stream = show' (&lt;kbd&gt;replicate&lt;/kbd&gt; 5 &lt;kbd&gt;undefined&lt;/kbd&gt;) stream&lt;br /&gt;&gt;        &lt;kbd&gt;where&lt;/kbd&gt; show' [] _ = "..."&lt;br /&gt;&gt;              show' (_:t) (x :&amp;lt; xs)&lt;br /&gt;&gt;                    = &lt;kbd&gt;show&lt;/kbd&gt; x ++ " :&amp;lt; " ++ show' t xs&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Functor Stream&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;fmap&lt;/kbd&gt; f (x :&amp;lt; xs) = f x :&amp;lt; &lt;kbd&gt;fmap&lt;/kbd&gt; f xs&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Copointed Stream&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    extract (v :&amp;lt; _) = v&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Comonad Stream&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    extend f stream@(x :&amp;lt; xs) = f stream :&amp;lt; extend f xs&lt;br /&gt;&lt;br /&gt;&gt; produce :: (a &amp;rarr; a) &amp;rarr; a &amp;rarr; &lt;tt&gt;Stream&lt;/tt&gt; a&lt;br /&gt;&gt; produce f seed = &lt;kbd&gt;let&lt;/kbd&gt; x = f seed &lt;kbd&gt;in&lt;/kbd&gt; x :&amp;lt; produce f x&lt;br /&gt;&lt;br /&gt;Um, it is the user's responsibility &lt;br /&gt;to guard these functions below ...&lt;br /&gt;&lt;br /&gt;&gt; toList :: &lt;tt&gt;Stream&lt;/tt&gt; a &amp;rarr; [a]&lt;br /&gt;&gt; toList (x :&amp;lt; xs) = x : toList xs&lt;br /&gt;&lt;br /&gt;&gt; mapS :: (a &amp;rarr; b) &amp;rarr; &lt;tt&gt;Stream&lt;/tt&gt; a &amp;rarr; &lt;tt&gt;Stream&lt;/tt&gt; b&lt;br /&gt;&gt; mapS = &lt;kbd&gt;fmap&lt;/kbd&gt;&lt;/pre&gt;&lt;/blockquote&gt;As for lists, it is quite easy to make streams an instance of the Comonad class.  So, a stream of 1s is &lt;blockquote&gt;&lt;pre&gt;let ones = 1 :&amp;lt; (ones =&gt;&gt; (extract &gt;&gt;&gt; &lt;kbd&gt;id&lt;/kbd&gt;))&lt;br /&gt;ones &amp;equiv; 1 :&amp;lt; 1 :&amp;lt; 1 :&amp;lt; 1 :&amp;lt; 1 :&amp;lt; ...&lt;/pre&gt;&lt;/blockquote&gt;The natural numbers are&lt;blockquote&gt;&lt;pre&gt;let nats = 0 :&amp;lt; (nats =&gt;&gt; (extract &gt;&gt;&gt; &lt;kbd&gt;succ&lt;/kbd&gt;))&lt;br /&gt;nats &amp;equiv; 0 :&amp;lt; 1 :&amp;lt; 2 :&amp;lt; 3 :&amp;lt; 4 :&amp;lt; ...&lt;/pre&gt;&lt;/blockquote&gt;And a stream of primes is ... um, yeah.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;... of primes&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The ease at which we generated the stream of 1s and natural numbers would lead one to believe that generating primes would follow the same pattern.  The difference here is that a prime number is a number not divisible evenly by &lt;em&gt;any other&lt;/em&gt; prime number.  So, with the schema for streams as above, one would need to know all the prime numbers to find this prime number.  A problem perfectly suited for comonads, so it would seem, but, as the current element of the stream depends on the instantiation of the entire breadth of the stream, we run into a bit of a time problem waiting for our system to calculate the &lt;em&gt;entire&lt;/em&gt; stream of primes in order to compute the current prime. Hm.&lt;br /&gt;&lt;br /&gt;One needs to put some thought into how to go about computing a stream of primes.  Uustalu and Vene created the concepts of &lt;tt&gt;Delay&lt;/tt&gt; and &lt;tt&gt;Antic&lt;/tt&gt;ipation along with a &lt;tt&gt;History&lt;/tt&gt;.  All that is outside the scope of this article.  Instead, let's consider &lt;tt&gt;Stream&lt;/tt&gt; in a different light: why not embed the "history" (the primes we know) into the &lt;tt&gt;Stream&lt;/tt&gt; itself.  And what is the history?  Is it not a list?&lt;blockquote&gt;&lt;pre&gt;&gt; primeHist :: &lt;tt&gt;Stream&lt;/tt&gt; [&lt;tt&gt;Integer&lt;/tt&gt;]&lt;br /&gt;&gt; primeHist = [3,2] :&amp;lt; primeHist =&gt;&gt; get'&lt;/pre&gt;&lt;/blockquote&gt;With that understanding, our outstanding function to find the current prime (&lt;code&gt;get'&lt;/code&gt;) reduces to the standard Haskell hackery:&lt;blockquote&gt;&lt;pre&gt;&gt; get' :: &lt;tt&gt;Stream&lt;/tt&gt; [&lt;tt&gt;Integer&lt;/tt&gt;] &amp;rarr; [&lt;tt&gt;Integer&lt;/tt&gt;]&lt;br /&gt;&gt; get' stream = &lt;kbd&gt;let&lt;/kbd&gt; primus = extract stream&lt;br /&gt;&gt;                   candidate = &lt;kbd&gt;head&lt;/kbd&gt; primus + 2&lt;br /&gt;&gt;               &lt;kbd&gt;in&lt;/kbd&gt;  getsome' candidate primus&lt;br /&gt;&gt;      &lt;kbd&gt;where&lt;/kbd&gt; getsome' :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; [&lt;tt&gt;Integer&lt;/tt&gt;] &amp;rarr; [&lt;tt&gt;Integer&lt;/tt&gt;]&lt;br /&gt;&gt;            getsome' candidate primus&lt;br /&gt;&gt;               = &lt;kbd&gt;if all&lt;/kbd&gt; (&amp;lambda;p . candidate `&lt;kbd&gt;rem&lt;/kbd&gt;` p &amp;ne; 0) primus&lt;br /&gt;&gt;                 &lt;kbd&gt;then&lt;/kbd&gt; candidate : primus&lt;br /&gt;&gt;                 &lt;kbd&gt;else&lt;/kbd&gt; getsome' (2 + candidate) primus&lt;/pre&gt;&lt;/blockquote&gt;So, now we have a stream of histories of primes, to convert that into a stream of primes is a simple step:&lt;blockquote&gt;&lt;code&gt;&gt; primes = 2 :&amp;lt; (3 :&amp;lt; &lt;kbd&gt;fmap head&lt;/kbd&gt; primeHist)&lt;/code&gt;&lt;/blockquote&gt;And there you have it, a comonadic stream of primes!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Critique&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Uustalu and Vene's implementation of &lt;code&gt;prime&lt;/code&gt; suffer for the layers of complexity, but my implementation suffers at least as much for its relative simplicity.  &lt;em&gt;Each element&lt;/em&gt; of the stream contains the history of all the primes up to that prime.  A much more efficient approach, both in space and time, would be to use the &lt;tt&gt;State&lt;/tt&gt; monad or comonad to encapsulate and to grow the history as the state ... or, for that matter, just use list compression.  &lt;br /&gt;&lt;br /&gt;And, of course, there's the "Genuine Sieve of Eratosthenes" [O'Neill, circa 2006] that this article blithely ignored.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1104451234541062591?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1104451234541062591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1104451234541062591' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1104451234541062591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1104451234541062591'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/09/stream-of-primes-as-comonad.html' title='A stream of primes as Comonad'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1947312519386931575</id><published>2008-08-29T16:16:00.000-07:00</published><updated>2008-08-29T17:11:46.780-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='housekeeping'/><title type='text'>Earning ⊥-Trophies</title><content type='html'>I recall a quote stating that a person learns Haskell by reinventing the standard library.  I'm still learning Haskell.  Marvel Comics would give out a "No Prize" to each intrepid reader who noted discrepancies of plot or character.  In that spirit, and in the spirit of functional/logical programming of my blog, I'll happily award &amp;perp;-trophies to readers who point out improvements to my definitions that elicits a &lt;a href='http://www.larrythemarine.net/2008/01/view_image.html'&gt;facepalm&lt;/a&gt; reaction (so, yes, this is a highly subjective award), and add the reader's id as well as the function I've unintentionally redefined (or the equivalent) to a "Hall of Fame" gadget adorning this blog (if you prefer to abstain from the recognition, that's fine, too).&lt;br /&gt;&lt;br /&gt;As this &amp;perp;-trophy set is part of the &lt;a href='http://en.wikipedia.org/wiki/Noosphere'&gt;νούςσφαίρα&lt;/a&gt;, there's no limitations: one person can receive several of these things, with my gratitude to the earner for giving me a piece of knowledge on how to be a better programmer.&lt;br /&gt;&lt;br /&gt;The &amp;perp;-trophy-winners so far (this will surely be a growing list) are, most recent first:&lt;ul&gt;&lt;li&gt;meteficha: &lt;kbd&gt;takeWhile&lt;/kbd&gt;&lt;/li&gt;&lt;li&gt;dmwit: &lt;code&gt;join&lt;/code&gt;&lt;/li&gt;&lt;li&gt;matti: &lt;code&gt;ap&lt;/code&gt;&lt;/li&gt;&lt;li&gt;ryani: &lt;code&gt;v&lt;/code&gt;&lt;/li&gt;&lt;li&gt;david: &lt;code&gt;u&lt;/code&gt;&lt;/li&gt;&lt;li&gt;edward kmett: &lt;tt&gt;Monoid&lt;/tt&gt;&lt;li&gt;Daniel Lyons: &lt;tt&gt;Arrow&lt;/tt&gt;&lt;/ul&gt;Mentor &amp;perp;-trophy-winners:&lt;ul&gt;&lt;li&gt;sigfpe&lt;/li&gt;&lt;li&gt;Dirk Thierbach&lt;/li&gt;&lt;li&gt;Wouter Swierstra&lt;/li&gt;&lt;/ul&gt;Honorary mentions (nice, but I'm not going use them for philosophical or stylistic reasons):&lt;ul&gt;&lt;li&gt;meteficha: &lt;code&gt;liftM2&lt;/code&gt;&lt;/li&gt;&lt;li&gt;ryani: &lt;code&gt;unsafeCoerce&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;The &amp;perp;-trophies up for grabs:&lt;ul&gt;&lt;li&gt;comonadic scanner-parser that simplifies the &lt;tt&gt;StateT&lt;/tt&gt; implementation&lt;/li&gt;&lt;li&gt;&lt;kbd&gt;shows&lt;/kbd&gt; for &lt;tt&gt;DList&lt;/tt&gt;&lt;/li&gt;&lt;li&gt;A good working (useful) example from the scan-family of functions&lt;/li&gt;&lt;/ul&gt;...so, yes, I've been thinking about scanning/parsing recently, but, of course, &lt;em&gt;any&lt;/em&gt; amazing little thing is up for grabs to earn oneself a &amp;perp;-trophy.&lt;br /&gt;&lt;br /&gt;And, now, back to our regularly scheduled programming.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1947312519386931575?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1947312519386931575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1947312519386931575' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1947312519386931575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1947312519386931575'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/earning.html' title='Earning &amp;perp;-Trophies'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-8572976427330157103</id><published>2008-08-29T13:00:00.000-07:00</published><updated>2008-08-29T16:16:20.783-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='monad transformers'/><title type='text'>Scanner-parsers II: State Monad Transformers</title><content type='html'>Okay, let's implement the same &lt;a href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-i-lifting-functions.html'&gt;Mars rover command language&lt;/a&gt; with pretty much the same solution, but this time, for our scanner-parser of the &lt;tt&gt;Position&lt;/tt&gt;, we're going to use the &lt;a href='http://www.haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-State-Lazy.html'&gt;&lt;tt&gt;StateT&lt;/tt&gt;&lt;/a&gt; monad transformer over the list monad to erase the housekeeping of the input stream.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;MarsRoverStateMonad&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;.&lt;tt&gt;State&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;... other imports and &lt;kbd&gt;data&lt;/kbd&gt;/&lt;kbd&gt;instance&lt;/kbd&gt; definitions as before ...&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;Recall our &lt;tt&gt;Scan&lt;/tt&gt; type was&lt;blockquote&gt;&lt;code&gt;&gt; -- &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Scan&lt;/tt&gt; = &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; (a, &lt;tt&gt;String&lt;/tt&gt;)&lt;/code&gt;&lt;/blockquote&gt;This type looks exactly like the type for the &lt;tt&gt;State&lt;/tt&gt; monad, and that documentation page reveals that parsing is very well handled by the &lt;code&gt;&lt;tt&gt;StateT&amp;nbsp;String&lt;/tt&gt;&amp;nbsp;[]&amp;nbsp;a&lt;/code&gt; type.  Let's transform our &lt;tt&gt;Scan&lt;/tt&gt; type into a monad:&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Scan&lt;/tt&gt; a = &lt;tt&gt;StateT String&lt;/tt&gt; [] a&lt;/code&gt;&lt;/blockquote&gt;Since, also, everything in the &lt;tt&gt;Position&lt;/tt&gt; data type derives the class &lt;tt&gt;Read&lt;/tt&gt; it becomes a simple matter to constrain our polymorphic type (&lt;code&gt;a&lt;/code&gt;) to the values we wish to obtain from our parser, like so:&lt;blockquote&gt;&lt;pre&gt;&gt; next :: &lt;tt&gt;Read&lt;/tt&gt; a &amp;rArr; &lt;tt&gt;Scan&lt;/tt&gt; a&lt;br /&gt;&gt; next = get &gt;&gt;= &amp;lambda;(x:xs) . put xs &gt;&gt; &lt;kbd&gt;if&lt;/kbd&gt; x &amp;equiv; ' ' &lt;br /&gt;&gt;                                    &lt;kbd&gt;then&lt;/kbd&gt; next &lt;br /&gt;&gt;                                    &lt;kbd&gt;else return&lt;/kbd&gt; (&lt;kbd&gt;read&lt;/kbd&gt; [x])&lt;/pre&gt;&lt;/blockquote&gt;This function, &lt;code&gt;next&lt;/code&gt;, is very simple for two reasons: first, the only separator that concerns us in this command language is the space (ASCII 32), and second, the tokens it consumes are only one character each.  Both of these simplicities in this language can be easily and obviously enhanced when implementing scanner-parsers for richer languages.&lt;br /&gt;&lt;br /&gt;With this new scanner (&lt;code&gt;next&lt;/code&gt;) based on the &lt;tt&gt;StateT&lt;/tt&gt; monad transformer, we can now rewrite our lifting functions in the monadic style.  This frees us to concentrate on the token at the current position and lets the monad handle the stream positioning.&lt;blockquote&gt;&lt;pre&gt;&gt; liftLoc = next &gt;&gt;= &amp;lambda;x . next &gt;&gt;= &amp;lambda;y . &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y)&lt;br /&gt;&gt; liftOrient = next&lt;br /&gt;&gt; liftPos = liftLoc &gt;&gt;= &amp;lambda;loc .&lt;br /&gt;&gt;           liftOrient &gt;&gt;= &amp;lambda;dir . &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Pos&lt;/tt&gt; loc dir)&lt;/pre&gt;&lt;/blockquote&gt;Note that the abstraction of the type signatures of these functions did not change at all, but the implementations simplified significantly (that is, if you consider the monadic style a simplification over the previous implementation that uses &lt;kbd&gt;let&lt;/kbd&gt;-bindings to sequence computations).&lt;br /&gt;&lt;br /&gt;Now to run the system, we replace in &lt;code&gt;runRovers&lt;/code&gt; the&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;let&lt;/kbd&gt; (start, _) = liftPos pos&lt;/code&gt;&lt;/blockquote&gt;with&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;let&lt;/kbd&gt; start = &lt;kbd&gt;head&lt;/kbd&gt; $ evalStateT (liftPos) pos&lt;/code&gt;&lt;/blockquote&gt;and we're done!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Critique&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I like the monadic threading much, &lt;em&gt;much&lt;/em&gt;, better than the previous implementation that manually threaded the position of the input stream via tupling using &lt;kbd&gt;let&lt;/kbd&gt;-bindings, but this version here also leaves something to be desired.  Note the parsing functions (&lt;code&gt;liftPos&lt;/code&gt; and &lt;code&gt;liftLoc&lt;/code&gt;) both follow the the format of:&lt;blockquote&gt;&lt;code&gt;grabA &gt;&gt;= &amp;lambda;a . grabB &gt;&gt;= &amp;lambda;b . return (&lt;tt&gt;&amp;Tau;&lt;/tt&gt; a b)&lt;/code&gt;&lt;/blockquote&gt;I don't like that I need to identify and bind the variables &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;; I don't like that one bit!  In my eyes, identifying these variables does nothing to make the program more declarative.  I would much rather write these functions in the following manner...&lt;blockquote&gt;&lt;pre&gt;&gt; liftLoc = next &gt;&gt;=&gt; next &gt;=&gt;&gt; &lt;tt&gt;Loc&lt;/tt&gt;&lt;br /&gt;&gt; liftPos = liftLoc &gt;&gt;=&gt; liftOrient &gt;=&gt;&gt; &lt;tt&gt;Pos&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;...with the my weird monadic stream operators defined (obviously) as follows...&lt;blockquote&gt;&lt;pre&gt;&gt; (&gt;&gt;=&gt;) :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m a &amp;rarr; m b &amp;rarr; m (a, m b)&lt;br /&gt;&gt; mA &gt;&gt;=&gt; mB = mA &gt;&gt;= &amp;lambda;a . &lt;kbd&gt;return&lt;/kbd&gt; (a, mB)&lt;br /&gt;&lt;br /&gt;&gt; (&gt;=&gt;&gt;) :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m (a, m b) &amp;rarr; (a &amp;rarr; b &amp;rarr; c) &amp;rarr; m c&lt;br /&gt;&gt; mTup &gt;=&gt;&gt; &amp;tau; = mTup &gt;&gt;= &amp;lambda;(a, mB) . &lt;br /&gt;&gt;               mB &gt;&gt;= &amp;lambda;b . &lt;kbd&gt;return&lt;/kbd&gt; (&amp;tau; a b)&lt;/pre&gt;&lt;/blockquote&gt;...but then I worry that this syntax is too esoteric for its own good.  Thoughts?&lt;br /&gt;&lt;br /&gt;Yes, a person leaving a remark pointed out that I've reinvented &lt;code&gt;liftM2&lt;/code&gt;.  Obviously so, in retrospect.  I'm on a roll!  After a year of entries, I suppose I'll have reinvented most of Haskell's standard library.&lt;br /&gt;&lt;br /&gt;Actually for binary situations (that is, for types that take two arguments from the stream to construct), I think I will use these special streaming monadic operators, but when types become more complex, then more, and more complex, operators are required (each new argument for a type &lt;em&gt;doubles&lt;/em&gt; the complexity of each new operator).  This tells me (as it has already told Uustalu and Vene) that monads are not the best way to go about scanning/parsing streams to extract an internal representation of the grammar.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-8572976427330157103?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/8572976427330157103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=8572976427330157103' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8572976427330157103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8572976427330157103'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-ii-state-monad.html' title='Scanner-parsers II: State Monad Transformers'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-4961735862097369157</id><published>2008-08-28T19:25:00.000-07:00</published><updated>2008-08-29T15:21:05.292-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parsing'/><title type='text'>Scanner-parsers I: lifting functions</title><content type='html'>I'll start right off with an apology:  I would've loved this entry to be on comonadic parsing, but I'm still trying to get my head around the Uustalu and Vene papers &amp;mdash; I keep looking in the papers for something that says the equivalent of "... and this comonadic parsing technique resolves to something very much like Prolog's definite clause grammar", but I didn't see this conclusion in their papers.  Would somebody please point out the gap in my understanding?&lt;br /&gt;&lt;br /&gt;Instead, we'll concentrate on converting a very simple command language into an internal representation using lifting functions.  &lt;a href='http://storytotell.org/articles/2007/04/08/haskell-arrows'&gt;Daniel Lyon&lt;/a&gt; suggested this "Mars rover" problem.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;MarsRover&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Char&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;List&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;strong&gt;Problem statement: MARS ROVERS&lt;/strong&gt;&lt;blockquote&gt;A squad of robotic rovers are to be landed by NASA on a plateau on Mars. This plateau, which is curiously rectangular, must be navigated by the rovers so that their on-board cameras can get a complete view of the surrounding terrain to send back to Earth.&lt;br /&gt;&lt;br /&gt;A rover's position and location is represented by a combination of x and y co-ordinates and a letter representing one of the four cardinal compass points. The plateau is divided up into a grid to simplify navigation. An example position might be 0, 0, N, which means the rover is in the bottom left corner and facing North.&lt;br /&gt;&lt;br /&gt;In order to control a rover, NASA sends a simple string of letters. The possible letters are 'L', 'R' and 'M'. 'L' and 'R' makes the rover spin 90 degrees left or right respectively, without moving from its current spot. 'M' means move forward one grid point, and maintain the same heading.&lt;br /&gt;&lt;br /&gt;Assume that the square directly North from (x, y) is (x, y+1).&lt;br /&gt;&lt;br /&gt;INPUT:&lt;br /&gt;&lt;br /&gt;The first line of input is the upper-right coordinates of the plateau, the lower-left coordinates are assumed to be 0,0.&lt;br /&gt;&lt;br /&gt;The rest of the input is information pertaining to the rovers that have been deployed. Each rover has two lines of input. The first line gives the rover's position, and the second line is a series of instructions telling the rover how to explore the plateau.&lt;br /&gt;&lt;br /&gt;The position is made up of two integers and a letter separated by spaces, corresponding to the x and y co-ordinates and the rover's orientation.&lt;br /&gt;&lt;br /&gt;Each rover will be finished sequentially, which means that the second rover won't start to move until the first one has finished moving.&lt;br /&gt;&lt;br /&gt;OUTPUT&lt;br /&gt;&lt;br /&gt;The output for each rover should be its final co-ordinates and heading.&lt;br /&gt;&lt;br /&gt;INPUT AND OUTPUT&lt;br /&gt;&lt;br /&gt;Test Input:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;5 5&lt;br /&gt;1 2 N&lt;br /&gt;LMLMLMLMM&lt;br /&gt;3 3 E&lt;br /&gt;MMRMMRMRRM&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Expected Output:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;1 3 N&lt;br /&gt;5 1 E&lt;/code&gt;&lt;/blockquote&gt;&lt;strong&gt;Problem solution&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Types&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;This problem simply decodes into a state machine and a command interpreter, where the interpreter first lifts the input characters into their correspondingly-typed values.&lt;blockquote&gt;&lt;pre&gt;The state machine, a.k.a Mars Rover, is:&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Location&lt;/tt&gt; = &lt;tt&gt;Loc Integer Integer&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Orientation&lt;/tt&gt; = &lt;tt&gt;N&lt;/tt&gt; | &lt;tt&gt;E&lt;/tt&gt; | &lt;tt&gt;S&lt;/tt&gt; | &lt;tt&gt;W&lt;/tt&gt;&lt;br /&gt;&gt;      deriving (&lt;tt&gt;Show&lt;/tt&gt;, &lt;tt&gt;Enum&lt;/tt&gt;, &lt;tt&gt;Read&lt;/tt&gt;)&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Position&lt;/tt&gt; = &lt;tt&gt;Pos Location Orientation&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;The typed commands are:&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Direction&lt;/tt&gt; = &lt;tt&gt;L&lt;/tt&gt; | &lt;tt&gt;R&lt;/tt&gt; deriving &lt;tt&gt;Show&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Command&lt;/tt&gt; = &lt;tt&gt;Turn Direction&lt;/tt&gt; | &lt;tt&gt;Move&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;... with some Show instances for sanity checks and output&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Command&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Turn&lt;/tt&gt; dir) = &lt;kbd&gt;show&lt;/kbd&gt; dir&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Move&lt;/tt&gt; = "M"&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Location&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y) = &lt;kbd&gt;show&lt;/kbd&gt; x ++ " " ++ &lt;kbd&gt;show&lt;/kbd&gt; y&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show Position&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Pos&lt;/tt&gt; loc dir) = &lt;kbd&gt;show&lt;/kbd&gt; loc ++ " " ++ &lt;kbd&gt;show&lt;/kbd&gt; dir&lt;/pre&gt;&lt;/blockquote&gt;Our scanner-parser for our very simple language grabs the next thing to be scanned from the input and returns updated input.&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Scan&lt;/tt&gt; a = &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; (a, &lt;tt&gt;String&lt;/tt&gt;)&lt;/code&gt;&lt;/blockquote&gt;&lt;strong&gt;Lifting functions&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The lifting functions are rather simple affairs, as they convert what's in the input stream to their typed internal equivalents:&lt;blockquote&gt;&lt;pre&gt;&gt; liftOrient :: &lt;tt&gt;Scan Orientation&lt;/tt&gt;&lt;br /&gt;&gt; liftOrient command = &lt;kbd&gt;head&lt;/kbd&gt; $ &lt;kbd&gt;reads&lt;/kbd&gt; command&lt;br /&gt;&lt;br /&gt;&gt; liftLoc :: &lt;tt&gt;Scan Location&lt;/tt&gt;&lt;br /&gt;&gt; liftLoc command = &lt;kbd&gt;let&lt;/kbd&gt; (x, locstr):_ = &lt;kbd&gt;reads&lt;/kbd&gt; command&lt;br /&gt;&gt;                       (y, out):_ = &lt;kbd&gt;reads&lt;/kbd&gt; locstr&lt;br /&gt;&gt;                   &lt;kbd&gt;in&lt;/kbd&gt;  (Loc x y, out)&lt;/pre&gt;&lt;/blockquote&gt;... I'm not quite getting the intent of &lt;kbd&gt;reads&lt;/kbd&gt;: it seems to return either empty (denoting failure) or a singleton list containing the value and the continuation (that is, to be precise, the rest of the list after the first value is read).  I'm not doubting its utility, but I do wonder that the list type was the return type if it behaves as a semideterimistic function (fail or singleton success) and not as a nondeterministic one (fail or multiple successes).  The &lt;tt&gt;Maybe&lt;/tt&gt; data type is more closely aligned with semideterministic functions; lists, nondet.  So I believe that either the &lt;tt&gt;Either&lt;/tt&gt; type or &lt;tt&gt;Maybe&lt;/tt&gt; are a more appropriate return for &lt;kbd&gt;reads&lt;/kbd&gt;.&lt;br /&gt;&lt;br /&gt;At any rate, with the above two lifting functions, lifting the position of the rover (the first line in our command language) simplifies to chaining the above two lifting functions:&lt;blockquote&gt;&lt;pre&gt;&gt; liftPos :: &lt;tt&gt;Scan Position&lt;/tt&gt;&lt;br /&gt;&gt; liftPos command = &lt;kbd&gt;let&lt;/kbd&gt; (loc, rest) = liftLoc command&lt;br /&gt;&gt;                       (dir, out)  = liftOrient rest&lt;br /&gt;&gt;                   &lt;kbd&gt;in&lt;/kbd&gt;  (&lt;tt&gt;Pos&lt;/tt&gt; loc dir, out)&lt;/pre&gt;&lt;/blockquote&gt;So, we have the scan and parse of the starting position of the rover done.  We're half-way there!  Now we simply need to scan then to parse the commands.  But, the neat thing for us is the following: the commands are atomic (and just one character each).  There's no need for the continuation scheme that we used for scanning positions above, we just need simply map the command lifting function over the line of commands (the "command line") to obtain our internal representation:&lt;blockquote&gt;&lt;pre&gt;&gt; liftCmd :: &lt;tt&gt;Char&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Command&lt;/tt&gt;&lt;br /&gt;&gt; liftCmd 'L' = &lt;tt&gt;Turn L&lt;/tt&gt;&lt;br /&gt;&gt; liftCmd 'R' = &lt;tt&gt;Turn R&lt;/tt&gt;&lt;br /&gt;&gt; liftCmd 'M' = &lt;tt&gt;Move&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;strong&gt;Command interpreter&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;What does a command do?  It moves the rover or reorients the rover.  What is movement? A change in &lt;tt&gt;Position&lt;/tt&gt; (via a change in &lt;tt&gt;Location&lt;/tt&gt;).  What is reorientation? A change in &lt;tt&gt;Orientation&lt;/tt&gt;.  So, a &lt;tt&gt;Command&lt;/tt&gt;'s action (which is either to &lt;code&gt;move&lt;/code&gt; or to &lt;code&gt;turn&lt;/code&gt; the rover) results in a &lt;tt&gt;&amp;Delta;&lt;/tt&gt; (pron: "Delta") of the &lt;tt&gt;Position&lt;/tt&gt;:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;&amp;Delta;&lt;/tt&gt; a = a &amp;rarr; a&lt;br /&gt;&lt;br /&gt;&gt; command :: &lt;tt&gt;Command&lt;/tt&gt; &amp;rarr; &lt;tt&gt;&amp;Delta; Position&lt;/tt&gt;&lt;br /&gt;&gt; command (&lt;tt&gt;Turn&lt;/tt&gt; dir) (&lt;tt&gt;Pos&lt;/tt&gt; loc orient)&lt;br /&gt;&gt;         = &lt;tt&gt;Pos&lt;/tt&gt; loc (turn dir orient)&lt;br /&gt;&gt; command &lt;tt&gt;Move&lt;/tt&gt; pos = move pos&lt;br /&gt;&lt;br /&gt;&gt; move :: &lt;tt&gt;&amp;Delta; Position&lt;/tt&gt;&lt;br /&gt;&gt; move (&lt;tt&gt;Pos&lt;/tt&gt; loc dir) = &lt;tt&gt;Pos&lt;/tt&gt; (dLoc dir loc) dir&lt;br /&gt;&gt;       where dLoc :: &lt;tt&gt;Orientation&lt;/tt&gt; &amp;rarr; &lt;tt&gt;&amp;Delta; Location&lt;/tt&gt;&lt;br /&gt;&gt;             dLoc &lt;tt&gt;N&lt;/tt&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y) = &lt;tt&gt;Loc&lt;/tt&gt; x (y+1)&lt;br /&gt;&gt;             dLoc &lt;tt&gt;E&lt;/tt&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y) = &lt;tt&gt;Loc&lt;/tt&gt; (x+1) y&lt;br /&gt;&gt;             dLoc &lt;tt&gt;W&lt;/tt&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y) = &lt;tt&gt;Loc&lt;/tt&gt; (x-1) y&lt;br /&gt;&gt;             dLoc &lt;tt&gt;S&lt;/tt&gt; (&lt;tt&gt;Loc&lt;/tt&gt; x y) = &lt;tt&gt;Loc&lt;/tt&gt; x (y-1)&lt;br /&gt;&lt;br /&gt;&gt; turn :: &lt;tt&gt;Direction&lt;/tt&gt; &amp;rarr; &lt;tt&gt;&amp;Delta; Orientation&lt;/tt&gt;&lt;br /&gt;&gt; turn dir orient&lt;br /&gt;&gt;      = &lt;kbd&gt;toEnum&lt;/kbd&gt; $ (intVal dir + &lt;kbd&gt;fromEnum&lt;/kbd&gt; orient) `&lt;kbd&gt;mod&lt;/kbd&gt;` 4&lt;br /&gt;&gt;       &lt;kbd&gt;where&lt;/kbd&gt; intVal :: &lt;tt&gt;Direction&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt;&lt;br /&gt;&gt;             intVal &lt;tt&gt;L&lt;/tt&gt; = -1&lt;br /&gt;&gt;             intVal &lt;tt&gt;R&lt;/tt&gt; = 1&lt;/pre&gt;&lt;/blockquote&gt;I suppose &lt;code&gt;turn&lt;/code&gt; could've been modeled more realistically on radians, and would work just the same, but since the command language is so simple (turns are exactly 90&lt;small&gt;&lt;sup&gt;o&lt;/sup&gt;&lt;/small&gt;), I can get away with using the four points of the compass as (circularly) enumerated values.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Glue&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Given all the above, the rover simply runs as follows.&lt;blockquote&gt;Note that I ignore the grid-size command, as it appears to be superfluous to the problem definition (collision detection between rovers and out-of-the-grid bounding errors are NOT covered in the problem statement ... since they choose to ignore these issues, I will, too).&lt;pre&gt;&gt; runRovers :: &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;IO&lt;/tt&gt; ()&lt;br /&gt;&gt; runRovers commnd = &lt;kbd&gt;let&lt;/kbd&gt; (_:commands) = &lt;kbd&gt;lines&lt;/kbd&gt; commnd&lt;br /&gt;&gt;                    &lt;kbd&gt;in  putStrLn&lt;/kbd&gt; $ run' commands&lt;br /&gt;&gt;    &lt;kbd&gt;where&lt;/kbd&gt; run' [] = ""&lt;br /&gt;&gt;          run' (pos:cmds:rest)&lt;br /&gt;&gt;               = &lt;kbd&gt;let&lt;/kbd&gt; (start, _) = liftPos pos&lt;br /&gt;&gt;                     mycmds = &lt;kbd&gt;map&lt;/kbd&gt; liftCmd cmds&lt;br /&gt;&gt;                     stop = &lt;kbd&gt;foldl&lt;/kbd&gt; (&lt;kbd&gt;flip&lt;/kbd&gt; command)&lt;br /&gt;&gt;                                  start mycmds&lt;br /&gt;&gt;                 &lt;kbd&gt;in  show&lt;/kbd&gt; stop ++ "\n" ++ run' rest&lt;br /&gt;&lt;br /&gt;&gt; runTestEx :: &lt;tt&gt;IO&lt;/tt&gt; ()&lt;br /&gt;&gt; runTestEx = runRovers "5 5\n1 2 N\nLMLMLMLMM\n"&lt;br /&gt;&gt;                       ++ "3 3 E\nMMRMMRMRRM"&lt;/pre&gt;&lt;/blockquote&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;So, there you have it, folks: scanning and parsing as mapped lifting functions.  That all DSLs would be that simple, but that topic is for when I cover how I reinvent the &lt;a href='http://www.haskell.org/haskellwiki/Parsec'&gt;Parsec&lt;/a&gt; wheel ... but in the meantime, you can read the &lt;a href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-ii-state-monad.html'&gt;next extry&lt;/a&gt; the covers scanning and parsing for this problem with the &lt;tt&gt;State&lt;/tt&gt; monad transformer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-4961735862097369157?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/4961735862097369157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=4961735862097369157' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4961735862097369157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4961735862097369157'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/scanner-parsers-i-lifting-functions.html' title='Scanner-parsers I: lifting functions'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-5006456610698733171</id><published>2008-08-27T11:15:00.000-07:00</published><updated>2011-04-01T06:58:39.229-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nondeterminism'/><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><title type='text'>Ten = 1+2+3+4</title><content type='html'>Daniel Lyons on his blog, showed us how to how &lt;a href='http://storytotell.org/articles/2008/08/11/prolog'&gt;to arith our way to 10 in Prolog&lt;/a&gt; using the operations of addition, subtraction, multiplication, and division and the numbers 1, 2, 3, and 4.  A straightforward logic program, which I was hoping to duplicate the feel of in Haskell.  Here's my go at it.&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;module &lt;tt&gt;Ten&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control&lt;/tt&gt;.&lt;tt&gt;Monad&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;List&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;&lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;Smullyan&lt;/a&gt;&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I suppose the standard way people going about enumerating the arithmetic operations is to encode it in the following way ... &lt;blockquote&gt;&lt;pre&gt;&gt; {-&lt;br /&gt;&gt;    &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;BinaryOp&lt;/tt&gt; = &lt;tt&gt;Plus&lt;/tt&gt; | &lt;tt&gt;Minus&lt;/tt&gt; | &lt;tt&gt;Div&lt;/tt&gt; | &lt;tt&gt;Times&lt;/tt&gt; deriving &lt;tt&gt;Eq&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&gt;    op :: &lt;tt&gt;BinaryOp&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Int&lt;/tt&gt;&lt;br /&gt;&gt;    op &lt;tt&gt;Plus&lt;/tt&gt;  b a = &lt;tt&gt;Just&lt;/tt&gt; $ a + b&lt;br /&gt;&gt;    op &lt;tt&gt;Minus&lt;/tt&gt; b a = &lt;tt&gt;Just&lt;/tt&gt; $ a - b&lt;br /&gt;&gt;    op &lt;tt&gt;Times&lt;/tt&gt; b a = &lt;tt&gt;Just&lt;/tt&gt; $ a * b&lt;br /&gt;&gt;    op &lt;tt&gt;Div&lt;/tt&gt;   b a = &lt;kbd&gt;if&lt;/kbd&gt; b &amp;equiv; 0 &amp;or; a `&lt;kbd&gt;rem&lt;/kbd&gt;` b &amp;ne; 0 &lt;br /&gt;&gt;                   &lt;kbd&gt;then&lt;/kbd&gt; &lt;tt&gt;Nothing&lt;/tt&gt; &lt;br /&gt;&gt;                   &lt;kbd&gt;else&lt;/kbd&gt; &lt;tt&gt;Just&lt;/tt&gt; (a `&lt;kbd&gt;div&lt;/kbd&gt;` b)&lt;br /&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;instance &lt;tt&gt;Show BinaryOp&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;       &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Plus&lt;/tt&gt;  = "+"&lt;br /&gt;&gt;       &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Minus&lt;/tt&gt; = "-"&lt;br /&gt;&gt;       &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Div&lt;/tt&gt;   = "/"&lt;br /&gt;&gt;       &lt;kbd&gt;show&lt;/kbd&gt; &lt;tt&gt;Times&lt;/tt&gt; = "x"&lt;br /&gt;&gt; -}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... but I shied away from that approach for two reasons: first and foremost, we have a disjoint type with enumerated values, but later we are going to choose from those enumerated values from a list of all those values.  It seems to me to be wastefully redundant to enumerate the values of the type in its declaration, and then be required to enumerate those values again in their use.  Wastefully redundant and dangerous &amp;mdash; the type guarantees that I will not use values outside the type, but how can I guarantee that I've used all the values of the type in the program?  I'm mean, of course, besides full coverage using a dependently typed system, that is.&lt;br /&gt;&lt;br /&gt;So instead of the above commented out code, I chose the following type definition:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;BinaryOp&lt;/tt&gt; = &lt;tt&gt;Op&lt;/tt&gt; (&lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt;) &lt;tt&gt;String&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This type has the advantage that the arithmetic operation is embedded in the type itself, as well as showing and equality:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Eq BinaryOp&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    (&lt;tt&gt;Op&lt;/tt&gt; _ a) &amp;equiv; (&lt;tt&gt;Op&lt;/tt&gt; _ b) = a &amp;equiv; b&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance &lt;tt&gt;Show BinaryOp&lt;/tt&gt; where&lt;/kbd&gt;&lt;br /&gt;&gt;    &lt;kbd&gt;show&lt;/kbd&gt; (&lt;tt&gt;Op&lt;/tt&gt; _ s) = s&lt;br /&gt;&lt;br /&gt;&gt; op :: &lt;tt&gt;BinaryOp&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Int&lt;/tt&gt;&lt;br /&gt;&gt; op (&lt;tt&gt;Op&lt;/tt&gt; f s) b a | s &amp;equiv; "/"  = &lt;kbd&gt;if&lt;/kbd&gt; b &amp;equiv; 0 &amp;or; a `&lt;kbd&gt;rem&lt;/kbd&gt;` b &amp;ne; 0 &lt;br /&gt;&gt;                               &lt;kbd&gt;then&lt;/kbd&gt; &lt;tt&gt;Nothing&lt;/tt&gt; &lt;br /&gt;&gt;                               &lt;kbd&gt;else&lt;/kbd&gt; &lt;tt&gt;Just&lt;/tt&gt; (a `&lt;kbd&gt;div&lt;/kbd&gt;` b)&lt;br /&gt;&gt;                 | &lt;kbd&gt;otherwise&lt;/kbd&gt; = &lt;tt&gt;Just&lt;/tt&gt; $ f a b&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I know that some of you are going to be raising your eyebrows in disbelief: I've forsaken a pure and dependable, or compile-time, way to distinguish operations with a very weak string, or runtime, representation.  The former is "just the way it makes sense" for most; the latter, my "sensible" compromise, sacrificing type safety for a more declarative representation.  Again, if we had dependent types, I think there would be a type-safe way to represent arithmetic operators as comparable (distinct) and showable types ... dependent types for Haskell', anyone?&lt;br /&gt;&lt;br /&gt;Okay, now we need to write &lt;code&gt;permute&lt;/code&gt;, because this isn't C++ or Java.  *sigh*  That's correct, you heard it here first: Java and C++ are way better programming languages because they have &lt;code&gt;permute&lt;/code&gt; in their standard libraries, and Haskell does not.&lt;blockquote&gt;&lt;pre&gt;&gt; permute :: &lt;tt&gt;Eq&lt;/tt&gt; a &amp;rArr; [a] &amp;rarr; [[a]]&lt;br /&gt;&gt; permute list@(h:t) = [x:rest | x &amp;isin; list, &lt;br /&gt;&gt;                                rest &amp;isin; permute (list \\ [x])]&lt;br /&gt;&gt; permute [] = [[]]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And from that the solver simply follows:  it's the permutation of the row of numbers matched with any arbitrary (&lt;code&gt;amb&lt;/code&gt;iguous) arithmetic operation.  This has the flavor of the days when I was writing code in &lt;a href='http://digitize.textfiles.com/items/1983-mms-forth/'&gt;MMSForth&lt;/a&gt;, push the numbers on the stack and then call the operators.  Oh, &lt;a href='http://en.wikipedia.org/wiki/Joy_programming_language'&gt;JOY&lt;/a&gt;!  (I'll stop now.)&lt;blockquote&gt;&lt;pre&gt;&gt; solver = [twiner perms [op1, op2, op3] |&lt;br /&gt;&gt;                      perms@[a,b,c,d] &amp;isin; permute [1..4],&lt;br /&gt;&gt;                      op1 &amp;isin; amb, op2 &amp;isin; amb, op3 &amp;isin; amb,&lt;br /&gt;&gt;                      ((op op1 b a &gt;&gt;= op op2 c &gt;&gt;= op op3 d)&lt;br /&gt;&gt;                            &amp;equiv; &lt;tt&gt;Just&lt;/tt&gt; 10)]&lt;br /&gt;&lt;br /&gt;&gt; amb = [&lt;tt&gt;Op&lt;/tt&gt; (+) "+", &lt;tt&gt;Op&lt;/tt&gt; (*) "x", &lt;tt&gt;Op&lt;/tt&gt; &lt;kbd&gt;div&lt;/kbd&gt; "/", &lt;tt&gt;Op&lt;/tt&gt; (-) "-"]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, all we need is the display mechanic (&lt;code&gt;twiner&lt;/code&gt;) to intersperse the arithmetic operators between the provided numbers.  I had started down this path ...&lt;blockquote&gt;&lt;pre&gt;&gt; stringIt :: &lt;tt&gt;BinaryOp&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt; &amp;rarr; &lt;tt&gt;String&lt;/tt&gt;&lt;br /&gt;&gt; stringIt op num acc = "(" ++ acc ++ &lt;kbd&gt;show&lt;/kbd&gt; op ++ &lt;kbd&gt;show&lt;/kbd&gt; num ++ ")"&lt;br /&gt;&lt;br /&gt;&gt; twiner :: [&lt;tt&gt;Int&lt;/tt&gt;] &amp;rarr; [&lt;tt&gt;BinaryOp&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;String&lt;/tt&gt;&lt;br /&gt;&gt; {- &lt;br /&gt;&gt;    twiner args ops = doTwine args ops &lt;tt&gt;True&lt;/tt&gt; ""&lt;br /&gt;&gt;       where doTwine args ops binary acc | binary =&lt;br /&gt;&gt;                    let (arg1, rest) = (&lt;kbd&gt;head&lt;/kbd&gt; args, &lt;kbd&gt;tail&lt;/kbd&gt; args)&lt;br /&gt;&gt;                        (arg2, done) = (&lt;kbd&gt;head&lt;/kbd&gt; rest, &lt;kbd&gt;tail&lt;/kbd&gt; rest)&lt;br /&gt;&gt;                    in doTwine done (&lt;kbd&gt;tail&lt;/kbd&gt; ops) &lt;tt&gt;False&lt;/tt&gt; &lt;br /&gt;&gt;                               (stringIt (&lt;kbd&gt;head&lt;/kbd&gt; ops) arg2 (&lt;kbd&gt;show&lt;/kbd&gt; arg1))&lt;br /&gt;&gt;                                         | ops == [] = acc&lt;br /&gt;&gt;                                         | &lt;kbd&gt;otherwise&lt;/kbd&gt; =&lt;br /&gt;&gt;                       doTwine (&lt;kbd&gt;tail&lt;/kbd&gt; args) (&lt;kbd&gt;tail&lt;/kbd&gt; ops) &lt;tt&gt;False&lt;/tt&gt;&lt;br /&gt;&gt;                               (stringIt (&lt;kbd&gt;head&lt;/kbd&gt; ops) (&lt;kbd&gt;head&lt;/kbd&gt; args) acc)&lt;br /&gt;&gt; -}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... looking longingly at &lt;code&gt;intersperse&lt;/code&gt; in the &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;List&lt;/tt&gt; module (why, oh, why! can't they have &lt;code&gt;intersperse&lt;/code&gt; take a state-function argument? Oh, because I would be the only person using it?), but, I figured, as I have &lt;a href='http://logicaltypes.blogspot.com/2008/08/using-difference-lists.html'&gt;already reinvented &lt;kbd&gt;takeWhile&lt;/kbd&gt;&lt;/a&gt;, I had better not reinvent &lt;kbd&gt;zipWith&lt;/kbd&gt; here:&lt;blockquote&gt;&lt;pre&gt;&gt; twiner (h:r) ops = &lt;kbd&gt;foldl&lt;/kbd&gt; &lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;t&lt;/a&gt; (&lt;kbd&gt;show&lt;/kbd&gt; h) (doTwine r)&lt;br /&gt;&gt;    &lt;kbd&gt;where&lt;/kbd&gt; doTwine args = &lt;kbd&gt;zipWith&lt;/kbd&gt; (&lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;c&lt;/a&gt; stringIt) args ops&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... *ahem* &lt;small&gt;dependent types would guarantee that &lt;code&gt;twiner&lt;/code&gt; is never called with an empty list of arguments.&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;I'd say my Haskell version follows in the spirit of the &lt;a href='http://storytotell.org/articles/2008/08/11/prolog'&gt;Prolog version&lt;/a&gt; in that it uses nondeterminism (of the &lt;tt&gt;Maybe&lt;/tt&gt; and list &lt;tt&gt;MonadPlus&lt;/tt&gt; types) to select the true equations.  Weighing in at 18 lines of type declarations and code (with 4 additional lines for the module declaration and the imports), it is also about the same size as the Prolog version as well.&lt;br /&gt;&lt;br /&gt;Goodness! Typeful logic programming in Haskell, with all the functional frosting on the cake applied for free, costs no more than developing a Prolog program, and along with the type-safety, it also carries with it the flavor and the feel of logic programming in Prolog as well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-5006456610698733171?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/5006456610698733171/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=5006456610698733171' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5006456610698733171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5006456610698733171'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/ten-1234.html' title='Ten = 1+2+3+4'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-6140424625476617111</id><published>2008-08-26T20:08:00.000-07:00</published><updated>2008-08-27T11:15:02.682-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='on-the-job'/><title type='text'>"Lucky you!"?</title><content type='html'>I'm sure some of you reading this blog share my fortune in that you are getting paid to code declaratively.  I also know others of you are stuck in that ghetto of churning out web-pages from JSPs or VB.NET or Oracle Forms and are wondering how to break into that fairy-tale world where you can use a sentence with the word "&amp;lambda;-term" in it and not have it confused with a &lt;em&gt;Revenge of the Nerds&lt;/em&gt; reference.&lt;br /&gt;&lt;br /&gt;Yes, Virginia, there are actually jobs/contracts out there that pay real money for you to code declaratively.  In fact, if you're in the United States or Australia, then there are "lots" of these jobs, and, if you're in Europe or Asia, there are some jobs in your country or in a country near you.&lt;br /&gt;&lt;br /&gt;So, here you are, and you're missing the key ingredients that will secure you one of these plum assignments: professional work experience in your LoCh ("Language of Choice") 'cause your stuck writing VB scripts, not (e.g.) Haskell, and phone calls from recruiters or companies wanting (e.g.) Haskell programmers 'cause you don't have (e.g.) Haskell on your resum&amp;eacute; (because you never, ever lie on your resum&amp;eacute;) and 'cause no recruiter nor company will ever admit they need something other than a programmer with Java or C# experience if they are hunting.&lt;br /&gt;&lt;br /&gt;Real life story: a recruiter solicited me with no idea that I had Prolog experience for a Prolog req. because she was so used to seeking Java programmers, and all her other contracts needed Java programmers, that the thought never occurred to her.  Only my "and, yeah, I also have experience in Mercury, which is like Prolog, and Dylan, which is like Lisp" woke her up to that nagging req. that she thought she was never going fill.&lt;br /&gt;&lt;br /&gt;So, for all of you out there thinking about looking, you probably need a couple of questions answered.  Like: how do you prepare for these jobs, and then, how do you find them?  Well, I'm not going to give advice here on what &lt;em&gt;should&lt;/em&gt; work, I'm going to tell you &lt;em&gt;what worked for me&lt;/em&gt;.  But since my experience may be atypical, maybe some of the readership that do have functional or logical programming jobs can chime in with your own stories that show easier routes to success.&lt;br /&gt;&lt;br /&gt;Here's how I didn't get my paying jobs coding in Dylan and Mercury and Prolog and Haskell (yes, my current job is accepting some code in Haskell and they are building a foreign interface to Haskell in their Prolog engine.  Win!):&lt;ul&gt;&lt;li&gt;I neither lied on nor fudged my resum&amp;eacute;.&lt;br /&gt;&lt;br /&gt;Some people think that reading a book on Hibernate allows them to enter a bullet on their resum&amp;eacute; as on-the-job work experience.  Those kind of antics may get one in the door, but the thing that &lt;em&gt;keeps&lt;/em&gt; one on the payroll is "am I confident and competent building systems with this technology?" ("did I really do this?"), not "can I learn the technology I listed on my resume on the new job?" ("do I think I can do this?")&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;I didn't get my job from any of the companies listed on haskell.org or schemers.org or &amp;lt;anything&amp;gt;.org.&lt;br /&gt;&lt;br /&gt;Why? Because these listings are usually from somebody who got to write a code snippet or a pet project in their favorite language under the radar and are crowing about it on their-favorite-language.org website.  Sure it's wonderful that XYZ corp is using Haskell, but does the HR department know about it?  No. Is is in their budget to hire a Haskell programmer?  No.  You don't need to believe me on this one, however.  You can send an email to every single one of those companies, just like I did, and get the null-responses and the "this email address does not exist" bounces, just like I did.  Knock yourself out.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;I also didn't get a job or contract working for the luminous companies in the declarative world.&lt;br /&gt;&lt;br /&gt;Don't know why here, but I can guess.  It may be that Galois or Jane's Capital or Ericsson or whatever gets a few solicitations a quarter, and they are already up to their gills in talent.  If they already have all the work they want in that domain, and they have already some people with some time on their hands, they aren't going to hire a new person, and give that person nothing for their job, just because that new person is &lt;em&gt;so excited&lt;/em&gt; about the opportunity to code declaratively.&lt;br /&gt;&lt;br /&gt;And the larger the company, the harder it is to thread one's way through the layers of bureaucracy to reach the isolated island that uses your LoCh.  Sure, IBM (Tivoli) and Microsoft (Windows Registry) use Prolog, but good luck finding a person to speak about that in those empires.  And since your LoCh is so niche in those empire, good luck finding an opening.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;So, I guess it &lt;em&gt;was&lt;/em&gt; pure-D-luck that I was on four contracts where I used Dylan, and one contract where I used Smalltalk, and one contract where I used Mercury, and two contracts where I used Prolog, and one contract (so far) that I'm using Haskell.&lt;br /&gt;&lt;br /&gt;... or maybe not.&lt;br /&gt;&lt;br /&gt;So, how &lt;em&gt;did&lt;/em&gt; I get to use these languages that I (have) love(d) on these contracts?  &lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;First and foremost, by being the best &lt;em&gt;d*mned&lt;/em&gt; Java or C++ programmer their management had ever seen.  In 1996, I took three Java books on my honeymoon, &lt;em&gt;and read them&lt;/em&gt;.  (Yes, Virginia, 12 years later, we are still married.) Every single night after work on my C++ contracts, I would read something from &lt;em&gt;Design Patterns&lt;/em&gt; and Stroustrup.  Work assignment scoped to two months, end-to-end, I would complete in two weeks.&lt;br /&gt;&lt;br /&gt;What did that give me? Trust, latitude, tolerance and time.  Management knew they didn't need to look over my shoulder and they would allow me to do the jobs my way.  It then was a very simple step from writing each web-page as its own JSP to writing a Dylan program that generated 100s of JSPs from templates.  Then I would show management the Dylan program.  ("This, boss, is how I've been so efficient").&lt;br /&gt;&lt;br /&gt;Most of the time it worked ("That's awesome, Doug." "Would you be willing to be a reference for me?" "Sure."), sometimes it didn't ("How are we going to maintain this when you're gone?  Rewrite it in Java." "Yes, ma'am.").  Where it worked, I added it to my resum&amp;eacute;; where it didn't, I didn't.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Next, I was the best salesman in the organization, better, even than the PR department.  At socials with the customer, all the programmers would line up against the far wall ('cause programmers are shy, don't you know), except me.  I would cross the room and walk right up to the customer with a ready handshake ("Larry, hi; I'm Doug Auclair, and I'm working on solving your problems"), this also applied to internal customers ("Paul, nice to meet you; I'm glad the VP of ITT is checking out this satellite program").&lt;br /&gt;&lt;br /&gt;What did this get me? Call backs and word-of-mouth that allowed me to set the terms of the contract ("Hi, Doug, this is Bruce at Raytheon, we need somebody good on this new contract, so we called you."  "Sure, Bruce, this is my rate." "That won't be a problem").&lt;br /&gt;&lt;br /&gt;If you want what you want, you &lt;em&gt;must&lt;/em&gt; be good where you are and you &lt;em&gt;cannot&lt;/em&gt; be a wall-flower.  People with the power to decide must think of you first because a) you've excelled in your current work and b) you've told them so.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Next, I always had my eyes and ears open and, when I was good, I opened my mouth &lt;em&gt;only&lt;/em&gt; after someone had gotten their gripe off their chest.  You know what a gripe is?  To me, a gripe is a contract.  "!@#$%^*, we need a phoneme-based name-matcher but the programmer who built it in assembler retired years ago!" (Trans: &lt;em&gt;Doug, we need you to write a fuzzy ILP system in Mercury&lt;/em&gt;) "I sure wish we could use the function object templates you've written about in the C++ system I'm building." (Trans: &lt;em&gt;Doug, come on board to show me how Dylan will make this a whole bunch easier.&lt;/em&gt;) &lt;!-- "My customers won't pay their bills; I'm owed 10,000s of dollars" (Trans: &lt;em&gt;Doug, help me write a proposal for a multi-million dollar contract.&lt;/em&gt;) --&gt; "We want your system to extract meaning from text documents, but extracting meaning from the images is too hard; don't bother with that." (Trans: &lt;em&gt;Tell us about image processing and classification with Self-Organizing Maps and Pulse Coupled Neural Networks.&lt;/em&gt;).  Each of the above gripes led to work, that is authorization and funding, for me to write in &lt;em&gt;my&lt;/em&gt; LoCh (Mercury, Dylan, and Haskell) that was outside the, erhm, comfort-language of providing company.&lt;br /&gt;&lt;br /&gt;How did I have the confidence to offer those suggested courses of action and then have the competence to build them to delivery?  &lt;em&gt;Listening&lt;/em&gt; is &lt;em&gt;key&lt;/em&gt;.  &lt;em&gt;Nobody listens&lt;/em&gt; in our industry, so when somebody does listen, the griper is so relieved that somebody &lt;em&gt;cared&lt;/em&gt; that they weigh the response with much greater significance.  That I had these novel, but workable, courses of action to offer comes from what I did in the next, final, point.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Finally, I became a teacher.  Being a teacher, a real teacher, means first you are a learner and learn &lt;em&gt;more&lt;/em&gt; than anyone you know about the topic, and second you are a doer and are &lt;em&gt;better&lt;/em&gt; at using the technology to solve the given problems than anyone else on the team.  Those two things are prerequisites to being a teacher, but they don't make you a teacher.  No, to be a teacher, you must write, write, and then write some more about the topic: documentation (users manuals and programmer manuals), white papers, articles, quizzes, aphorisms.  Then after the writing comes the lecturing: I spent years developing and then teaching continuing education courses at the local community college after I gave brown bag lunch lectures at my place of work.  I got two of my better contracts from company owners tripping over my written materials: a Dylan project and a Prolog-based agent project.&lt;br /&gt;&lt;br /&gt;By the way, teaching is &lt;em&gt;not&lt;/em&gt; droning on for an hour or for four hours.  Teaching is preparation, to the tune of 13 hours of prep work for each hour in front of the class (I did).  Teaching is getting up on top of the desk to do flamenco (I did), teaching is jumping up and down, up and down, jackhammer-style to drill in the point (I did), teaching is having the students wonder what I was on and could they get a prescription ("Class, this is Doug &lt;em&gt;without coffee!&lt;/em&gt;").  Teaching is inspiration; it is the flame to ignite the students' imagination.&lt;br /&gt;&lt;br /&gt;I had something like 3,000 students under my tutelage from the brown bags and my continuing education courses (that I was paid to teach), from coders to company presidents ... do you think I have a problem with my contact network?&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Oh, but that's easy for an extrovert like you, Doug! But I'm naturally shy.&lt;/em&gt;  Dude, don't give me that line!  On Myers-Briggs, I'm either INFJ or INTJ, my "I" (introversion) is so extreme that it actually blows the percentile curve.  I HATE interacting with people, so much so that it takes an additional 8 hours for me to recover from a meeting or class that I run (and since I'm president of my independent consulting firm, I run &lt;em&gt;all&lt;/em&gt; the meetings and teach &lt;em&gt;all&lt;/em&gt; the classes), but I LOVE coding declaratively more.  Once you know what you &lt;em&gt;must&lt;/em&gt; have, you'll find a way to &lt;em&gt;get&lt;/em&gt; it.  The excuses you used to make for not getting what you must have become just that, excuses; when you have that burn, that's when you start finding &lt;em&gt;ways&lt;/em&gt; to the desired end.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Well, unlike Java jobs or C# jobs or VB jobs, where one can scan the newspaper or go to dice.com, these magical jobs are not the ones I get when recruiters solicit me (three times a day).  No, they appear between the cracks of the sky when it rends in two.  All but one contract (that &lt;em&gt;did&lt;/em&gt; come from dice.com) came from the company CEO pulling me aside or phoning me out of the blue from the materials I had published inside the company where I was employed, or from my web-sites on programming languages.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Usually&lt;/em&gt; and because of the exclusivity of the work it takes anywhere from at least 3 months to &lt;em&gt;2 years&lt;/em&gt; to secure these kinds of contracts, so the adage "Don't quit your day job" is an appropriate one here.  When I do get these contracts, however, they usually last longer (3 years) than the Java/C++/XML/web-services-code-grinder ones (that usually last around 6 months), and the peer group is much more intelligent, genteel and just plain more interesting than the code-grinding crowd.  Is is harder to find these magical contracts? Yes, they are rarified air.  But are they worth preparing for and then finding?  Definitely.&lt;br /&gt;&lt;br /&gt;So, yes, I was lucky to work on 7 paying contracts using declarative languages, because I was the best code-grinder on my current job, I used my LoCh effectively and then wrote about the successes and taught techniques to my peers, all of which luckily attracted the notice of hungry companies needing a competitive advantage.  &lt;br /&gt;&lt;br /&gt;Luck, you see, is when preparedness meets opportunity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-6140424625476617111?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/6140424625476617111/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=6140424625476617111' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6140424625476617111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6140424625476617111'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/lucky-you.html' title='&quot;Lucky you!&quot;?'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-5246081084778417088</id><published>2008-08-13T22:12:00.000-07:00</published><updated>2008-08-14T01:03:43.261-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='difference lists'/><title type='text'>Using Difference Lists</title><content type='html'>I posted my enthusiasm about difference lists for Haskell &lt;a href='http://logicaltypes.blogspot.com/2008/08/difference-lists-in-haskell.html'&gt;earlier this month&lt;/a&gt;, but then became sidetracked by &lt;a href='http://logicaltypes.blogspot.com/search/label/combinatory%20logic'&gt;combinators&lt;/a&gt; and &lt;a href='http://logicaltypes.blogspot.com/search/label/reading%20list'&gt;reading lists&lt;/a&gt;, so, let's get back on track.&lt;br /&gt;&lt;br /&gt;Difference lists are a (very) useful data structure in Prolog, particularly when it comes to parsing with &lt;a href='http://www.w3.org/People/cmsmcq/2004/lgintro.html'&gt;definite clause grammars&lt;/a&gt; (DCGs) and when it comes to list construction (again, using DCGs).  Why?  Well, to answer that question, let's examine the structure of difference lists.  The Prolog (or relational) representation of a difference list is of the form:&lt;blockquote&gt;&lt;code&gt;X = [1,2,3|Y] - Y&lt;/code&gt;&lt;/blockquote&gt;What that relation describes is that &lt;code&gt;X&lt;/code&gt; is the &lt;em&gt;difference&lt;/em&gt; of the pair of lists of (first) &lt;code&gt;[1,2,3]&lt;/code&gt; appended with the list &lt;code&gt;Y&lt;/code&gt; &lt;em&gt;minus&lt;/em&gt; (second) the list &lt;code&gt;Y&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Well, what is the value of the list &lt;code&gt;Y&lt;/code&gt;?  To a Prologian, this question is not important (for &lt;code&gt;Y&lt;/code&gt;, being a logic variable, can be &lt;em&gt;any&lt;/em&gt; list or, even, not a list at all because the variable is still uninstantiated (a "free" variable)).  Its importance is that it gives us an "instant" index into the list after the elements we've already processed.  The significance of that index for parsing is that we now have a stream over the parsed (list) data, which gives us the ability &lt;a href='http://64.233.169.104/search?q=cache:Y4uYX5-GrzQJ:ai.fri.uni-lj.si/gregorl/Students/TPJ/dcg.ppt+definite+clause+grammars+move+step&amp;hl=en&amp;ct=clnk&amp;cd=1&amp;gl=us&amp;client=firefox-a'&gt;to translate BNF grammars directly into working parsers&lt;/a&gt;.  The significance for list construction is that we "simply" walk "backward" through the DCG to construct a list from a (parsed) internal representation, without paying the linear cost of either (a) traversing the list each time to add a new element (which results in exponential time list construction) or (b) building the list in reverse (adding new elements to the head of the list) and then applying &lt;kbd&gt;reverse&lt;/kbd&gt; to the end result.&lt;br /&gt;&lt;br /&gt;"Big deal!" you scoff, "&lt;a href='http://en.wikibooks.org/wiki/Haskell/Zippers'&gt;zippers&lt;/a&gt; [also called 'finger trees'] already give us indices into data structures.  Who needs a funny-looking specialized zipper just for lists?"&lt;br /&gt;&lt;br /&gt;"Good point!" is my response.  Zippers are powerful and flexible data structures that not only provide that index over any data structure, but, even better than difference list's index that only goes forward (with any dignity) in constant time, the zipper's index can go both forward and backward through that (generic) structure in constant time.  So, if you are not familiar with zippers, I request that you run, don't walk, to a &lt;a href='http://en.wikibooks.org/wiki/Haskell/Zippers'&gt;good overview&lt;/a&gt; to learn more about their utility.&lt;br /&gt;&lt;br /&gt;With all their flexibility and power, in certain situations, a zipper is not the correct choice for some list processing tasks; the difference list's simplicity shines in these situations.  First, for the unidirectional index of the difference list (it moves forward through the list well, but backwards ... not so much), this, for list construction purposes, is hardly ever an issue, and if it becomes one, then backtracking is easily installed with some &lt;tt&gt;MonadPlus&lt;/tt&gt; magic.  Next, you, the coder, are responsible for constructing a zipper list data type each time you need one, but Don Stewart has provided &lt;a href='http://hackage.haskell.org/cgi-bin/hackage-scripts/package/dlist'&gt;Data.DList&lt;/a&gt;; no construction necessary!  Last, an example structure of a zipper list, for the list &lt;code&gt;a++b&lt;/code&gt; is &lt;code&gt;(&lt;kbd&gt;reverse&lt;/kbd&gt;&amp;nbsp;a,b)&lt;/code&gt;, so if we wish to reconstruct the original list, for an &lt;code&gt;a&lt;/code&gt; of large magnitude, we still pay the linear (&lt;kbd&gt;reverse&lt;/kbd&gt;) cost in reconstruction &lt;em&gt;as well as&lt;/em&gt; the linear cost of appending &lt;code&gt;b&lt;/code&gt; to that result.&lt;br /&gt;&lt;br /&gt;You heard it here first, folks &amp;mdash; difference lists: &lt;a href='http://www.youtube.com/watch?v=b9nptjUs9FM'&gt;[zipper lists] can't touch this!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Okay, I've finished throwing it down for now.  Let's look at difference lists from the Haskell perspective and then use this data structure in a list construction example.&lt;blockquote&gt;&lt;code&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Data&lt;/tt&gt;.&lt;tt&gt;DList&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;For my examples, I'm going to be looking at the subset of difference lists that I can compare and see:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Eq&lt;/tt&gt; a =&gt; &lt;tt&gt;Eq&lt;/tt&gt; (&lt;tt&gt;DList&lt;/tt&gt; a) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;     x == y = toList x == toList y&lt;br /&gt;&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; (&lt;tt&gt;Eq&lt;/tt&gt; a, &lt;tt&gt;Show&lt;/tt&gt; a) =&gt; &lt;tt&gt;Show&lt;/tt&gt; (&lt;tt&gt;DList&lt;/tt&gt; a) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;&gt;     &lt;kbd&gt;show&lt;/kbd&gt; x | x == empty = "\\x -&gt; [x]"&lt;br /&gt;&gt;            | &lt;kbd&gt;otherwise&lt;/kbd&gt;  = "\\x -&gt; [" ++ show (head x)&lt;br /&gt;&gt;                           ++ doShow (toList (tail x)) ++ ":x]"&lt;br /&gt;&gt;         &lt;kbd&gt;where&lt;/kbd&gt; doShow [] = ""&lt;br /&gt;&gt;               doShow (a:b) = ", " ++ show a ++ doShow b&lt;/pre&gt;&lt;/blockquote&gt;With the above &lt;kbd&gt;instance&lt;/kbd&gt; declarations, we see that&lt;blockquote&gt;&lt;code&gt;(singleton 1) `snoc` 2 `snoc` 3&lt;/code&gt;&lt;/blockquote&gt;gives us the representation&lt;blockquote&gt;&lt;code&gt;&amp;lambda; x . [1, 2, 3:x]&lt;/code&gt;&lt;/blockquote&gt;... &lt;code&gt;snoc&lt;/code&gt; appends an element to the end of a list (so it's the reverse of &lt;code&gt;cons&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Prologians are always smug with their ability to create an infinite stream of 1s with &lt;code&gt;X&amp;nbsp;=&amp;nbsp;[1|X]&lt;/code&gt;.  And, no doubt about it, Prolog is a programming language that makes list construction easy ... &lt;em&gt;*ahem* almost&lt;/em&gt; as &lt;a href='http://homepages.inf.ed.ac.uk/wadler/poem.html'&gt;easy as list construction in Haskell&lt;/a&gt; ("Your list comprehensions outshine even Prolog for sure..."):&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;repeat&lt;/kbd&gt; 1&lt;br /&gt;[1,1..]&lt;br /&gt;&lt;em&gt;... and now with difference lists ...&lt;/em&gt;&lt;br /&gt;&lt;kbd&gt;let&lt;/kbd&gt; x = unDL (singleton 1) x &lt;kbd&gt;in&lt;/kbd&gt; x&lt;/pre&gt;&lt;/blockquote&gt;But no self-respecting Prologian would freeze their interpreter with a such a rash proof; Haskellians have no such concern, thanks to weak head normal form:&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;take&lt;/kbd&gt; 5 (&lt;kbd&gt;repeat&lt;/kbd&gt; 1)&lt;/code&gt;&lt;/blockquote&gt;So there!&lt;br /&gt;&lt;br /&gt;Let's examine an application of difference lists.  I have a &lt;a href='http://logicaltypes.blogspot.com/2008/05/orators-exercise.html'&gt;little scanner&lt;/a&gt; that I use to help me in my &lt;a href='http://www.cotilliongroup.com/arts/en-verse.html'&gt;oration&lt;/a&gt;.  The meat of the algorithm (before difference lists) was as follows:&lt;blockquote&gt;&lt;pre&gt;&gt; lettersIn word = lettersIn' word []&lt;br /&gt;&lt;br /&gt;&gt; lettersIn' [] ans = &lt;kbd&gt;reverse&lt;/kbd&gt; ans&lt;br /&gt;&gt; lettersIn' (h:t) ans | isLetter h = lettersIn' t (h:ans)&lt;br /&gt;&gt;                      | &lt;kbd&gt;otherwise&lt;/kbd&gt;  = &lt;kbd&gt;reverse&lt;/kbd&gt; ans&lt;/pre&gt;&lt;/blockquote&gt;Ugh, yes, &lt;kbd&gt;reverse&lt;/kbd&gt;s galore!  This is an oft-recurring pattern in Haskell code that is very easily fixed with some difference list magic:&lt;blockquote&gt;&lt;pre&gt;&gt; lettersIn word = lettersIn' word empty&lt;br /&gt;&lt;br /&gt;&gt; lettersIn' [] ans = toList ans&lt;br /&gt;&gt; lettersIn' (h:t) ans | isLetter h = lettersIn' t (ans `snoc` h)&lt;br /&gt;&gt;                      | &lt;kbd&gt;otherwise&lt;/kbd&gt;  = toList ans&lt;/pre&gt;&lt;/blockquote&gt;A very simply example, I grant you, for if we take a list whose elements are all in the set of the alphabet, the above code is a very complicated way of reinventing the &lt;kbd&gt;id&lt;/kbd&gt; function.  Or, put another way, who's going to teach me about &lt;kbd&gt;scanl&lt;/kbd&gt;?  Hm, would I be required to use the &lt;a href='http://www.haskell.org/all_about_monads/html/contmonad.html'&gt;continuation &lt;tt&gt;Monad&lt;/tt&gt;&lt;/a&gt; to escape the scan, I wonder? But you get the general idea for list construction, right?  Instead of building the list by adding to the head ("cons"ing) and then applying &lt;kbd&gt;reverse&lt;/kbd&gt; to the result, the different list allows one to "&lt;code&gt;snoc&lt;/code&gt;" each element and return the correctly ordered result.  For a single list construction, the benefit may not be all that obvious, but when one builds, e.g., an XML generator for a complex internal representation, reversing the reverse of the reversed reversed child element becomes an odious labour &amp;mdash; difference lists eliminate all the internal juggling, replacing that complication with a straightforward constant-time list and element in-place append.&lt;br /&gt;&lt;br /&gt;So, next time you need to do some list construction, instead of falling back on the &lt;kbd&gt;reverse&lt;/kbd&gt; standby, flex your new difference list muscles; you'll be pleasantly surprised.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-5246081084778417088?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/5246081084778417088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=5246081084778417088' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5246081084778417088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5246081084778417088'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/using-difference-lists.html' title='Using Difference Lists'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1638087261496283909</id><published>2008-08-12T11:18:00.000-07:00</published><updated>2008-08-12T17:44:26.663-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='combinatory logic'/><title type='text'>Combinatory Birds as Types</title><content type='html'>This post is composed nearly entirely of the work of readers responding to my &lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;previous post&lt;/a&gt; that dealt with combinatory logic combinators.  That post implemented the &lt;a href='http://www.amazon.com/Mock-Mockingbird-Raymond-M-Smullyan/dp/0192801422'&gt;Smullyan combinatory birds&lt;/a&gt; as functions.  This is the obvious approach, as birds and &amp;lambda;-terms have a very simple and straightforward (obviously bidirectional) mapping.  A few readers improved and explained some of my combinators (&lt;code&gt;S&lt;/code&gt; and &lt;code&gt;W&lt;/code&gt;) by using the &lt;code&gt;((-&gt;) a) &lt;tt&gt;Monad&lt;/tt&gt;&lt;/code&gt;, and I rolled those improvements into the original post, but these improvements are still in the combinators-as-functions domain.&lt;br /&gt;&lt;br /&gt;Two readers, ryani and david, provided implementations for two combinators that I've had difficulty with.  &lt;a href='http://www.cotilliongroup.com/arts/void-meditations.html'&gt;I've implemented&lt;/a&gt; the "void" combinator from the &lt;a href='http://www.madore.org/~david/programs/unlambda/'&gt;Unlambda programming language&lt;/a&gt; (or as Smullyan calls it, the "hopelessly egocentric" bird) using only the &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt; combinators.  Haskell is (thankfully) not so restricted, so ryani implemented that combinator as a type and then as a class.  The thrust of ryani's void-as-type implementation is as follows:&lt;blockquote&gt;&lt;pre&gt;&gt; {-# LANGUAGE RankNTypes #-}&lt;br /&gt;&gt; &lt;kbd&gt;newtype&lt;/kbd&gt; &lt;tt&gt;Void&lt;/tt&gt; = &lt;tt&gt;V&lt;/tt&gt; { runV :: forall a. a -&gt; &lt;tt&gt;Void&lt;/tt&gt; }&lt;br /&gt;&gt; v :: &lt;tt&gt;Void&lt;/tt&gt;&lt;br /&gt;&gt; v = &lt;tt&gt;V&lt;/tt&gt; (\x -&gt; v)&lt;/pre&gt;&lt;/blockquote&gt;Simple and sweet!  And, the ranked type resolves the type-circularity ("void x is of type void").  So, for example:&lt;blockquote&gt;&lt;pre&gt;&gt; :t runV v 0&lt;br /&gt;runV v 0 :: Void&lt;br /&gt;&gt; :t runV v "hello"&lt;br /&gt;runV v "hello" :: Void&lt;br /&gt;&gt; :t runV (runV v 0) "hello"&lt;br /&gt;runV (runV v 0) "hello" :: Void&lt;br /&gt;&lt;em&gt;... etc ...&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;a href='http://www.cotilliongroup.com/arts/void-meditations.html'&gt;In my implementation&lt;/a&gt;, I represented that the "void" combinator is "enough" &lt;code&gt;K&lt;/code&gt; combinators (where "enough" was more &lt;code&gt;K&lt;/code&gt; combinators than applications); ryani takes that exact approach using a class-based implementation:&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;class&lt;/kbd&gt; &lt;tt&gt;Voidable&lt;/tt&gt; r &lt;kbd&gt;where&lt;/kbd&gt; vc :: r&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Voidable&lt;/tt&gt; () &lt;kbd&gt;where&lt;/kbd&gt; vc = ()&lt;br /&gt;&gt; &lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Voidable&lt;/tt&gt; r =&gt; &lt;tt&gt;Voidable&lt;/tt&gt; (a -&gt; r) &lt;kbd&gt;where&lt;/kbd&gt; vc = k vc&lt;/pre&gt;&lt;/blockquote&gt;(so void is represented as the Haskell type and datum &lt;code&gt;()&lt;/code&gt; (&lt;em&gt;pron&lt;/em&gt;: "unit")) e.g.:&lt;blockquote&gt;&lt;pre&gt;&gt; vc "hello" :: ()&lt;br /&gt;()&lt;br /&gt;&gt; vc "hello" 123 :: ()&lt;br /&gt;()&lt;br /&gt;&gt; vc "hello" 123 (&lt;tt&gt;Just&lt;/tt&gt; k) :: ()&lt;br /&gt;()&lt;/pre&gt;&lt;/blockquote&gt;As ryani points out, the type-checker supplies the correct number of &lt;code&gt;K&lt;/code&gt; combinators to match the number of function applications.  Neat!&lt;br /&gt;&lt;br /&gt;I had &lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;left a question&lt;/a&gt; on how to implement the &lt;code&gt;U&lt;/code&gt;, or Turing, combinator, and david demonstrated an implementation where the class of all combinatory birds were a type (with two free implementations of good-ole factorial, to boot):&lt;blockquote&gt;&lt;pre&gt;&gt; &lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Bird&lt;/tt&gt; a = &lt;tt&gt;B&lt;/tt&gt; (&lt;tt&gt;Bird&lt;/tt&gt; a -&gt; &lt;tt&gt;Bird&lt;/tt&gt; a) | &lt;tt&gt;Value&lt;/tt&gt; a&lt;br /&gt;&lt;br /&gt;&gt; app :: &lt;tt&gt;Bird&lt;/tt&gt; a -&gt; &lt;tt&gt;Bird&lt;/tt&gt; a -&gt; &lt;tt&gt;Bird&lt;/tt&gt; a&lt;br /&gt;&gt; app (&lt;tt&gt;B&lt;/tt&gt; f) x = f x&lt;br /&gt;&lt;br /&gt;&gt; lift :: (a -&gt; a) -&gt; &lt;tt&gt;Bird&lt;/tt&gt; a&lt;br /&gt;&gt; lift f = &lt;tt&gt;B&lt;/tt&gt; (\(&lt;tt&gt;Value&lt;/tt&gt; x) -&gt; &lt;tt&gt;Value&lt;/tt&gt; (f x))&lt;br /&gt;&lt;br /&gt;&gt; unlift :: &lt;tt&gt;Bird&lt;/tt&gt; a -&gt; (a -&gt; a)&lt;br /&gt;&gt; unlift f = \x -&gt; case (f `app` &lt;tt&gt;Value&lt;/tt&gt; x) of &lt;tt&gt;Value&lt;/tt&gt; y -&gt; y&lt;br /&gt;&lt;br /&gt;&gt; -- Uxy = y(xxy)&lt;br /&gt;&gt; u = &lt;tt&gt;B&lt;/tt&gt; (\x -&gt; &lt;tt&gt;B&lt;/tt&gt; (\y -&gt; y `app` (x `app` x `app` y)))&lt;br /&gt;&lt;br /&gt;&gt; -- sage1 = UU &lt;em&gt;[geophf mumbles: "Sweet!"]&lt;/em&gt;&lt;br /&gt;&gt; sage1 = u `app` u&lt;br /&gt;&lt;br /&gt;&gt; -- Yx = x(Yx)&lt;br /&gt;&gt; sage2 = &lt;tt&gt;B&lt;/tt&gt; (\x -&gt; x `app` (sage2 `app` x))&lt;br /&gt;&lt;br /&gt;&gt; fix f = unlift (sage1 `app` B (\g -&gt; lift (f (unlift g))))&lt;br /&gt;&gt; fix2 f = unlift (sage2 `app` B (\g -&gt; lift (f (unlift g))))&lt;br /&gt;&lt;br /&gt;&gt; facR :: (&lt;tt&gt;Integer&lt;/tt&gt; -&gt; &lt;tt&gt;Integer&lt;/tt&gt;) -&gt; &lt;tt&gt;Integer&lt;/tt&gt; -&gt; &lt;tt&gt;Integer&lt;/tt&gt;&lt;br /&gt;&gt; facR f n = &lt;kbd&gt;if&lt;/kbd&gt; n == 1 &lt;kbd&gt;then&lt;/kbd&gt; 1 &lt;kbd&gt;else&lt;/kbd&gt; n * f (n - 1)&lt;br /&gt;&lt;br /&gt;&gt; fac = fix facR&lt;br /&gt;&gt; fac2 = fix2 facR&lt;/pre&gt;&lt;/blockquote&gt;I'm sure both ryani and david would claim that the &lt;code&gt;M&lt;/code&gt; combinator (where &lt;code&gt;m&amp;nbsp;x&amp;nbsp;=&amp;nbsp;x&amp;nbsp;x&lt;/code&gt;), so useful in &lt;a href='http://www.amazon.com/Mock-Mockingbird-Raymond-M-Smullyan/dp/0192801422'&gt;Smullyan&lt;/a&gt; for implementing several birds (such as the "void" combinator), is not hard to do in Haskell given the above implementations.  Do you see how to do it?  Wanna race?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1638087261496283909?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1638087261496283909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1638087261496283909' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1638087261496283909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1638087261496283909'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/combinatory-birds-as-types.html' title='Combinatory Birds as Types'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-2165114463853412421</id><published>2008-08-12T11:02:00.000-07:00</published><updated>2008-08-12T11:18:10.580-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reading list'/><title type='text'>Getting Better, part ][</title><content type='html'>A reader wrote in follow up to the &lt;a href='http://logicaltypes.blogspot.com/2008/08/how-do-i-get-better.html'&gt;previous post&lt;/a&gt; ("How do I get better? A reading list") and asked "Which of the three following books has the most bang for the buck?&lt;ul&gt;&lt;li&gt;To Mock a Mockingbird, Smullyan&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Algorithms, a Functional Approach, Rabhi, LaPalme&lt;/li&gt;&lt;br /&gt;&lt;li&gt;How to Solve it, Modern Heuristics, Michalewicz/Fogel"&lt;/li&gt;&lt;/ul&gt;Not that I particularly agree that the above three are the top three of the larger book list, but I responded thusly:&lt;br /&gt;&lt;br /&gt;The difficulty lies in the differences in our opinion as to which direction the bang makes the buck well-invested.&lt;br /&gt;&lt;br /&gt;A facile answer, but also useless for you, I suppose, is that they all have a high bang/buck ratio, much more so than most the drivel out there.  So let me explain their utility to me, and perhaps that will help you make a more informed decision as to how to proceed.&lt;ul&gt;&lt;li&gt;&lt;em&gt;To Mock a Mockingbird&lt;/em&gt;, Smullyan: I absolutely consumed.  But are you ever going to use combinatory logic combinators when coding?  &lt;a href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html'&gt;I do&lt;/a&gt;, and no-one else in the world does (Okay, maybe David Turner still does an occasional SK bit of low-level coding).  But as an introduction to the magic of first class functions and construction through composition (that is, in other words, "Coding in the Haskell-style") there is no equals as to its lightness of touch as well as the density of concepts.  You &lt;em&gt;learn&lt;/em&gt; from this book and &lt;em&gt;delight&lt;/em&gt; in it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;Algorithms&lt;/em&gt;, Rabhi &amp;amp; LaPalme.  I carry this book incessantly, into meetings (where I am to be a passive participant), on trips, etc.  Certainly it teaches one about data structures and algorithms in Haskell, using practical examples.  But it also opens one's eyes to possibilities of programming.  It is a powerful (but not dense), little book.  It is, however, dated, especially in the light of the explosion of new ways to use more-recently developed mathematical structures (from category theory, particularly, monads, arrows, and comonads).  It does not cover these recent developments, but the ones it does cover, it covers extraordinarily well.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;em&gt;How to Solve It&lt;/em&gt;, Michaelwicz &amp;amp; Fogel. Thick, dense, impressive.  I don't think I've gotten much further than chapter 2 &amp;mdash; this is my fault, but it is also the book's unapologetic full coverage and well as its assumption that they are not addressing 7-year-olds that make progression, for me, at least, arduous.  Worth reading? Absolutely, as it addresses the fundamental problems of problem-solving (at the top of their list is that problem solving is hard, and our education has flippantly ignored that bald fact) and proposes solutions that are novel, scintillating, simple, and, once discovered, obvious.  I recommend you read more than the first three chapters in a book store (prepare to spend more than a few days in this task) to see if you can justify purchasing it for continued reading.&lt;/li&gt;&lt;/ul&gt;So, did I provide accurate guidance for the inquirer? Or, where my assessments off-base?  I won't disclose the choice the reader made, but I will ask instead: which book would you have selected given the above reviews?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-2165114463853412421?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/2165114463853412421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=2165114463853412421' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2165114463853412421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2165114463853412421'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/getting-better-part.html' title='Getting Better, part ]['/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-2416109497276884560</id><published>2008-08-03T18:32:00.000-07:00</published><updated>2008-08-03T19:10:31.976-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reading list'/><title type='text'>How do I get better?</title><content type='html'>I just fielded a question from a programmer who wishes to improve his (Haskell) programming skill, and I responded with a reading list (below) and a referral to the &lt;a href='http://projecteuler.net'&gt;Project Euler problems site&lt;/a&gt;.  But I also see this as an excellent question for myself.  How do you, genteel reader, recommend I improve my skill as a coder?  Or, put another way, what book, or books, and which article, or articles, so totally transformed you from J. Random Hacker to J. &amp;Uuml;ber Hacker (hacker being coder, or mathematician, or logician, or rule developer, or ...)?&lt;br /&gt;&lt;br /&gt;My list is as follows.  Would you kindly tell me what I need to read right now so I can see the light as you have?&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;Books for learning&lt;/strong&gt;&lt;/u&gt;:&lt;br /&gt;&lt;br /&gt;The Art of the Metaobject Protocol, Moon, et al&lt;br /&gt;To Mock a Mockingbird, Smullyan&lt;br /&gt;Reasoned Schemer, Bird, et al&lt;br /&gt;Algorithms, a Functional Approach, Rabhi, LaPalme&lt;br /&gt;Genetic Algorithms, Goldberg&lt;br /&gt;How to Solve it, Modern Heuristics, Michalewicz/Fogel&lt;br /&gt;Godel, Escher, Bach, an Eternal Golden Braid, Hofstadter&lt;br /&gt;Prolog Programming for AI, Bratko&lt;br /&gt;(and, after a year of programming in Prolog), Craft of Prolog, O'Keefe&lt;br /&gt;A Grammatical View of Logic Programming, Deransart/Maluszynski&lt;br /&gt;An Introduction to Mathematical Philosophy, Russell&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;Books for Joy&lt;/strong&gt;&lt;/u&gt;:&lt;br /&gt;&lt;br /&gt;Testaments Betrayed, Kundera&lt;br /&gt;Last Samurai, DeWitt&lt;br /&gt;Lord of Light, Zelzany&lt;br /&gt;American Gods, Gaiman&lt;br /&gt;Complete Enchanter, de Camp&lt;br /&gt;Moor's Last Sigh, Rushdie&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;strong&gt;Noosphere&lt;/strong&gt;&lt;/u&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a href='http://users.bigpond.net.au/d.keenan/Lambda/'&gt;"To Dissect a Mockingbird"&lt;/a&gt; article, Keenan&lt;br /&gt;&lt;a href='http://library.readscheme.org/page1.html'&gt;The lambda papers&lt;/a&gt;, Steele/Sussman&lt;br /&gt;&lt;a href='http://homepages.inf.ed.ac.uk/wadler/documents/steele-oopsla98.pdf'&gt;Growing a language&lt;/a&gt; article, Guy Steele&lt;br /&gt;&lt;a href='http://www.ai-junkie.com/ann/evolved/nnt1.html'&gt;AI Junkie&lt;/a&gt; site&lt;br /&gt;&lt;a href='http://sigfpe.blogspot.com/'&gt;sigfpe.blogspot.com&lt;/a&gt; blog&lt;br /&gt;&lt;a href='http://www.randomhacks.net/'&gt;randomhacks.net&lt;/a&gt; blog&lt;br /&gt;the &lt;a href='http://haskell.org/haskellwiki/The_Monad.Reader'&gt;Monad.Reader&lt;/a&gt; (on haskell.org)&lt;br /&gt;&lt;a href='http://comonad.com/reader/'&gt;Comonad.Reader&lt;/a&gt; blog&lt;br /&gt;"&lt;a href='http://web.cecs.pdx.edu/~antoy/Courses/TPFLP/lectures/MONADS/Noel/research/monads.html'&gt;What the Hell are Monads?&lt;/a&gt;" article, Winstanley&lt;br /&gt;"&lt;a href='http://uebb.cs.tu-berlin.de/~magr/pub/Transformers.en.html'&gt;Monad Transformers, Step by Step&lt;/a&gt;" article, Grabmueller&lt;br /&gt;"&lt;a href='http://haskell.org/arrows/'&gt;Generalising Monads to Arrows&lt;/a&gt;", Hughes&lt;br /&gt;"&lt;a href='http://en.wikibooks.org/wiki/Haskell/Zippers'&gt;Theseus and the Zipper&lt;/a&gt;", on the Haskell Wiki&lt;br /&gt;"&lt;a href='http://web.engr.oregonstate.edu/~erwig/zurg/'&gt;Escape from Zurg: Exercise in Logic Programming&lt;/a&gt;",  Erwig&lt;br /&gt;And for language construction/deconstruction: &lt;a href='http://homepages.cwi.nl/~tromp/cl/lazy-k.html'&gt;Lazy K, Jot, Iota&lt;/a&gt; and &lt;a href='http://www.bigzaphod.org/whirl/'&gt;Whirl&lt;/a&gt; (well, at least they aren't INTERCAL ...), ... I suppose &lt;a href='http://www.muppetlabs.com/~breadbox/bf/'&gt;brainf**k&lt;/a&gt; should be mentioned here too ...&lt;br /&gt;"The tale of N-categories" serial, starting with &lt;a href='http://math.ucr.edu/home/baez/week73.html'&gt;week 73&lt;/a&gt;, Baez&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-2416109497276884560?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/2416109497276884560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=2416109497276884560' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2416109497276884560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2416109497276884560'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/how-do-i-get-better.html' title='How do I get better?'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-514998442583306914</id><published>2008-08-02T20:14:00.000-07:00</published><updated>2008-08-04T11:49:36.785-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='combinatory logic'/><title type='text'>Combinators in Haskell</title><content type='html'>In this article, instead of continuing along my path of shoving Prolog (predicate logic) into Haskell, I'll take a break from that and shove Haskell into Haskell.  This turn comes by way of my recent professional experience working with Prolog &amp;mdash; I found myself oftentimes needing to write some purely functional code, but I found the Prolog semantics getting in my way, so, borrowing some of the ideas from my previous professional programming experiences with &lt;a href='http://www.cs.mu.oz.au/research/mercury/'&gt;Mercury&lt;/a&gt; and &lt;a href='http://www.opendylan.org/'&gt;Dylan&lt;/a&gt; (when Harlequin was still a going concern, and had picked up the Dylan ball that Apple, then CMU, dropped, making a really sweet Dylan programming environment), I implemented a &lt;a href='http://www.cotilliongroup.com/libraries.html'&gt;set of libraries&lt;/a&gt; for Prolog, including basic ZF-set operations, propositional logic syntax, list/set/bag utilities, and the combinator logic of Sch&amp;ouml;nfinkel.&lt;br /&gt;&lt;blockquote&gt;"geophf!" You exclaim, horrified, "you don't really use combinators to write working production code, do you?"&lt;/blockquote&gt;&lt;br /&gt;Well, yes, and I also proposed a &lt;a href='http://www.cotilliongroup.com/arts/penguin.html'&gt;new one&lt;/a&gt; in addition to the ones covered by Smullyan in &lt;a href='http://www.amazon.com/Mock-Mockingbird-Raymond-M-Smullyan/dp/0192801422'&gt;&lt;em&gt;To Mock a Mockingbird&lt;/em&gt;&lt;/a&gt;, and have &lt;a href='http://www.cotilliongroup.com/arts/void-meditations.html'&gt;studied the make-up of the "void" combinator&lt;/a&gt; of &lt;a href='http://www.madore.org/~david/programs/unlambda/'&gt;Unlambda&lt;/a&gt;, so I'm one of those kinds of programmers.&lt;br /&gt;&lt;br /&gt;In short, when I was working with Prolog, I shoe-horned a Haskell interpreter into to be able to write map and fold when I wished to write map and fold.  Since Prolog has &lt;a href='http://www.cotilliongroup.com/arts/DCG.html'&gt;DCGs&lt;/a&gt; (Definite Clause Grammars), I lived a monad-free and worry-free life.  Ah, yes, those were the days.&lt;br /&gt;&lt;br /&gt;That was quite a trip down memory lane.  Looking back, I marvel at my fortune, not only have I professionally programmed in those languages (and VisualWorks Smalltalk; that was fun when I presented the boss a solution in two weeks that he was expecting in two months &amp;mdash; he was so impressed that he bought the VisualWorks system for the contract, made me mentor a junior programmer on Smalltalk (Chris Choe, a good guy to work with), and had me teach a brown bag course at work on Smalltalk, but I digress, again), but it looks like Haskell is now part of our solution at my current place of work.&lt;br /&gt;&lt;br /&gt;Life is good.&lt;br /&gt;&lt;br /&gt;Of course, it would be so much better if I had access to the primitive combinators in Haskell (did Miranda allow that kind of low-level access, I wonder).  I mean, why should one write out '&lt;kbd&gt;const&lt;/kbd&gt;', a whole FIVE characters, when one simply wishes to use the &lt;code&gt;K&lt;/code&gt; combinator.  &lt;a href='http://logicaltypes.blogspot.com/2008/07/dont-know-dont-care-whatever.html#bk3'&gt;I felt that very pain&lt;/a&gt; all too recently.  I had that freedom using my &lt;a href='http://www.cotilliongroup.com/man/combinators-man.html'&gt;combinator library&lt;/a&gt; when I was working on Prolog ... goodness, even MITRE fabricated the Curry Chip.&lt;br /&gt;&lt;br /&gt;So, I could not put it off any longer, I pulled out my dog-eared copy of &lt;em&gt;Mockingbird&lt;/em&gt; and wrote the CL module, as I didn't see one in the Haskell &lt;a href='http://haskell.org/ghc/docs/latest/html/libraries/'&gt;standard library&lt;/a&gt;.  It went surprisingly quickly and easily.  There were a few snags, Prolog, being dynamically-typed, allowed me to define the reoccuring combinators of &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, and &lt;code&gt;U&lt;/code&gt; (definitions of the combinators are available in &lt;a href='http://www.cotilliongroup.com/man/combinators-man.html'&gt;my combinator library&lt;/a&gt; or &lt;a href='http://www.angelfire.com/tx4/cus/combinator/birds.html'&gt;tabled form&lt;/a&gt; or &lt;a href='http://users.bigpond.net.au/d.keenan/Lambda/'&gt;as graphical notation&lt;/a&gt; (which includes a very nice write up of propositional logic in CL)), but Haskell's type system complains of an occur-check error.  I have the hack to define the &lt;code&gt;Y&lt;/code&gt; combinator ...&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;fix f = &lt;kbd&gt;let&lt;/kbd&gt; x = f x &lt;kbd&gt;in&lt;/kbd&gt; x&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;... but I'm having difficulty hacking the other self-applying combinators; any suggestions on how to implement those?  I'm particularly interested in implementing Turings' universal combinator ...&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;Uxy = y(xxy)&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;... because of its interesting properties I'd like to explore.&lt;br /&gt;&lt;br /&gt;Anyway, here's the ones I do have.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&gt; &lt;kbd&gt;module&lt;/kbd&gt; &lt;tt&gt;Smullyan&lt;/tt&gt; &lt;kbd&gt;where&lt;/kbd&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;It was pointed out to me in the comments that if you make the ((-&gt;) a) type a Monad, then some of the combinators simplify to monadic operators.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Monad&lt;/tt&gt;&lt;br /&gt;&gt; &lt;kbd&gt;import&lt;/kbd&gt; &lt;tt&gt;Control.Monad.Instances&lt;/tt&gt;&lt;/pre&gt;&lt;br /&gt;These are some of the combinators presented in Smullyan's &lt;em&gt;To Mock a Mockingbird&lt;/em&gt;.  Some have direct Haskell equivalents, e.g.: &lt;code&gt;I&lt;/code&gt; &amp;equiv; &lt;kbd&gt;id&lt;/kbd&gt;, &lt;code&gt;K&lt;/code&gt; &amp;equiv; &lt;kbd&gt;const&lt;/kbd&gt;, &lt;code&gt;C&lt;/code&gt; &amp;equiv; &lt;kbd&gt;flip&lt;/kbd&gt;, &lt;code&gt;B&lt;/code&gt; &amp;equiv; &lt;code&gt;(.)&lt;/code&gt;, but then that just makes my job easier here.  I also admit a preference to the Sch&amp;ouml;nfinkel combinators over the renamed Haskell equivalents, so here is the library.&lt;br /&gt;&lt;br /&gt;We will not be defining combinators here that cause an occurs-check of the type system, e.g. &lt;code&gt;L&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;U&lt;/code&gt;, but we can define some interesting ones, such as &lt;code&gt;O&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt; by using work-arounds.&lt;br /&gt;&lt;br /&gt;If we wish to start with &amp;lambda;&lt;sub&gt;I&lt;/sub&gt;, then its basis is formed from the &lt;code&gt;J&lt;/code&gt; and &lt;code&gt;I&lt;/code&gt; combinators.&lt;br /&gt;&lt;pre&gt;&gt; -- identity (I have no idea to which species belongs the 'identity' bird)&lt;br /&gt;&gt; i :: a -&gt; a&lt;br /&gt;&gt; i = &lt;kbd&gt;id&lt;/kbd&gt;&lt;br /&gt;&lt;br /&gt;&gt; -- jay: jabcd = ab(adc)&lt;br /&gt;&gt; j :: (a -&gt; b -&gt; b) -&gt; a -&gt; b -&gt; a -&gt; b&lt;br /&gt;&gt; j a b c d = a b (a d c)&lt;/pre&gt;&lt;br /&gt;I actually spent quite a stretch of time building the other combinators from the JI-basis, e.g., the &lt;code&gt;T&lt;/code&gt; combinator is &lt;code&gt;JII&lt;/code&gt;, the &lt;code&gt;Q&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; combinator is &lt;code&gt;JI&lt;/code&gt;, etc.  When I attempted to define the &lt;code&gt;K&lt;/code&gt; combinator, I ran into a brick wall for some time, until I reread the section in &lt;em&gt;Mockingbird&lt;/em&gt; about how the noble basis has no way to define that abhorred combinator.  Since that time I've fallen from grace and have used &amp;lambda;&lt;sub&gt;K&lt;/sub&gt;, but I've always wondered since if a complete logic could be reasonably expressed in &amp;lambda;&lt;sub&gt;I&lt;/sub&gt;, and if so, how would that logic be implemented?  I haven't come across any papers that address these questions.&lt;br /&gt;&lt;br /&gt;Musing again, let's define the basis of &amp;lambda;&lt;sub&gt;K&lt;/sub&gt; which is founded on the &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt; combinators.&lt;br /&gt;&lt;pre&gt;&gt; -- starling: sfgx = fx(gx)&lt;br /&gt;&gt; s :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m (a &amp;rarr; b) &amp;rarr; m a &amp;rarr; m b&lt;br /&gt;&gt; s = ap&lt;br /&gt;&lt;br /&gt;&gt; -- kestrel: kab = a&lt;br /&gt;&gt; k :: a -&gt; b -&gt; a&lt;br /&gt;&gt; k = &lt;kbd&gt;const&lt;/kbd&gt;&lt;/pre&gt;&lt;br /&gt;... okay, that wasn't too hard, so, &lt;code&gt;SKK&lt;/code&gt; should be &lt;code&gt;I&lt;/code&gt;, right?&lt;br /&gt;&lt;br /&gt;&lt;code&gt; --- :t (s k k) :: a -&gt; a&lt;/code&gt; ... oh, yeah!&lt;br /&gt;&lt;br /&gt;let's continue with some of the other combinators:&lt;br /&gt;&lt;pre&gt;&gt; -- bluebird: bfgx = f(gx)&lt;br /&gt;&gt; b :: (b -&gt; c) -&gt; (a -&gt; b) -&gt; a -&gt; c&lt;br /&gt;&gt; b = (.)&lt;br /&gt;&lt;br /&gt;&gt; -- cardinal: cfgx = gfx&lt;br /&gt;&gt; c :: (a -&gt; b -&gt; c) -&gt; b -&gt; a -&gt; c&lt;br /&gt;&gt; c = &lt;kbd&gt;flip&lt;/kbd&gt;&lt;/pre&gt;&lt;br /&gt;Now we start defining combinators in terms of simpler combinators.  Although, we could have started doing that once we've defined &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt;, as all other combinators can be derived from those two.&lt;br /&gt;&lt;pre&gt;&gt; -- dove: dfghx = fg(hx)&lt;br /&gt;&gt; d :: (d -&gt; b -&gt; c) -&gt; d -&gt; (a -&gt; b) -&gt; a -&gt; c&lt;br /&gt;&gt; d = b b&lt;br /&gt;&lt;br /&gt;&gt; -- thrush: txf = fx&lt;br /&gt;&gt; t :: a -&gt; (a -&gt; b) -&gt; b&lt;br /&gt;&gt; t = c i&lt;br /&gt;&lt;br /&gt;&gt; -- vireo (pairing/list): vabf = fab&lt;br /&gt;&gt; -- e.g. v 1 [2] (:) -&gt; [1,2]&lt;br /&gt;&gt; v :: a -&gt; b -&gt; (a -&gt; b -&gt; b) -&gt; b&lt;br /&gt;&gt; v = b c t&lt;br /&gt;&lt;br /&gt;&gt; -- robin: rxfy = fyx&lt;br /&gt;&gt; r :: a -&gt; (b -&gt; a -&gt; c) -&gt; b -&gt; c&lt;br /&gt;&gt; r = b b t&lt;br /&gt;&lt;br /&gt;&gt; -- owl: ofg = g(fg)&lt;br /&gt;&gt; o :: ((a -&gt; b) -&gt; a) -&gt; (a -&gt; b) -&gt; b&lt;br /&gt;&gt; o = s i&lt;br /&gt;&lt;br /&gt;&gt; -- queer: qfgx = g(fx)&lt;br /&gt;&gt; q :: (a -&gt; b) -&gt; (b -&gt; c) -&gt; a -&gt; c&lt;br /&gt;&gt; q = c b&lt;/pre&gt;&lt;br /&gt;-- mockingbird: mf = ff&lt;br /&gt;m = s i i&lt;br /&gt;&lt;br /&gt;... ah, well, it was worth a try ...&lt;br /&gt;&lt;pre&gt;&gt; -- warbler: wfx = fxx&lt;br /&gt;&gt; w :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m (m a) &amp;rarr; m a&lt;br /&gt;&gt; w = join&lt;br /&gt;&lt;br /&gt;&gt; -- eagle: eabcde = ab(cde)&lt;br /&gt;&gt; e :: (a -&gt; b -&gt; c) -&gt; a -&gt; (d -&gt; e -&gt; b) -&gt; d -&gt; e -&gt; c&lt;br /&gt;&gt; e = b (b b b)&lt;/pre&gt;&lt;br /&gt;With the above definitions, we can now type-check that my &lt;code&gt;JI&lt;/code&gt;-basis is correct: the type of &lt;code&gt;I&lt;/code&gt; already checks, and the type of &lt;code&gt;J&lt;/code&gt; should be equivalent to &lt;code&gt;B(BC)(W(BCE)))&lt;/code&gt;, ... &lt;br /&gt;&lt;pre&gt;:t (b (b c) (w (b c e)))&lt;br /&gt;(b (b c) (w (b c e))) :: (d -&gt; e -&gt; e) -&gt; d -&gt; e -&gt; d -&gt; e&lt;/pre&gt;&lt;br /&gt;and it is ... yay!&lt;br /&gt;&lt;br /&gt;-- lark (ascending): lfg = f(gg)&lt;br /&gt;l = ((s ((s (k s)) k)) (k (s i i)))&lt;br /&gt;&lt;br /&gt;l :: (a -&gt; b) -&gt; (c -&gt; a) -&gt; b&lt;br /&gt;a b = a (b b)&lt;br /&gt;&lt;br /&gt;... ah, well, another one bites the dust ...&lt;br /&gt;&lt;br /&gt;but we can define &lt;code&gt;Y&lt;/code&gt;, albeit with a let-trick, thanks to Dirk Thierbach, responding to the thread "State Monad Style" on comp.lang.haskell:&lt;br /&gt;&lt;pre&gt;&gt; fix :: (a -&gt; a) -&gt; a&lt;br /&gt;&gt; fix f = &lt;kbd&gt;let&lt;/kbd&gt; x = f x &lt;kbd&gt;in&lt;/kbd&gt; x&lt;br /&gt;&lt;br /&gt;&gt; -- sage/why: yf = f(yf)&lt;br /&gt;&gt; y :: (a -&gt; a) -&gt; a&lt;br /&gt;&gt; y = fix&lt;/pre&gt;&lt;br /&gt;So, there you go, 15 combinators to get you started; now you can program a functionally pure and mathematically sound version of Unlambda (which exists and is called &lt;a href='http://homepages.cwi.nl/~tromp/cl/lazy-k.html'&gt;Lazy-K&lt;/a&gt;, by the way) using your very own Haskell system.&lt;br /&gt;&lt;br /&gt;After all, why should someone ever be forced to write &lt;code&gt;\x -&gt; x^2&lt;/code&gt; when they have the option, and privilege, to write &lt;code&gt;w (*)&lt;/code&gt; instead?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-514998442583306914?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/514998442583306914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=514998442583306914' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/514998442583306914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/514998442583306914'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/combinators-in-haskell.html' title='Combinators in Haskell'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-6333965421069584475</id><published>2008-08-02T16:33:00.000-07:00</published><updated>2008-08-03T17:35:02.873-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='housekeeping'/><title type='text'>Apologies for late Spring cleaning</title><content type='html'>It was pointed out to me that the colour cyan is difficult to read against a white background; my syntax highlighter outputs Haskell keywords as cyan, so I understand that reading the code here can be bothersome.  So, I'm in the process of converting the cyan to a darker colour (which first involved me converting every &amp;lt;font color='cyan'&gt; to &amp;lt;font color='#00c8c8'&gt;, but then, part way through that process, I moved all font metadata to the stylesheet and now simply mark code, keywords and data types with appropriate metadata tags).&lt;br /&gt;&lt;br /&gt;A bit of a long-winded apology for what you may see as several (and repeated) repostings from this blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-6333965421069584475?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/6333965421069584475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=6333965421069584475' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6333965421069584475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6333965421069584475'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/apologies-for-late-spring-cleaning.html' title='Apologies for late Spring cleaning'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-8224486014686045212</id><published>2008-08-02T09:34:00.000-07:00</published><updated>2008-08-02T11:01:24.400-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='license'/><title type='text'>Legal Disclaimer</title><content type='html'>Parties:  &lt;br /&gt;&lt;br /&gt;"I", "me", "my", "mine", the author, geophf, aka Douglas M. Auclair&lt;br /&gt;"You", "your", the reader, user, coder, redistributor, referencer.  Some non-exhaustive examples of "You" include, J. Random Coder, J. Random Corporation, J. Random Defense Agency, J. Random Financial Institute, J. Random Blog, J. Random for-profit corporation/LLC, J. Random Sovereignty, or http://planet.haskell.org ... just as examples.&lt;br /&gt;"This blog", http://logicaltypes.blogspot.com, its content and entries originating from me.&lt;br /&gt;&lt;br /&gt;License:&lt;br /&gt;&lt;br /&gt;The words of this blog, http://logicaltypes.blogspot.com, are freely available to be read, to be commented on, to be referenced, or to be copied.  I, the author, would like attribution, either to this site (an URL as reference is appropriate) or to the author, geophf, aka Douglas M. Auclair, but do not require it.  I would also like to know if you find the topics discussed here useful, by either leaving a comment on this blog in the standard fashion, or by sending me an email at the scrambled email address of doug.at.cotilliongroup.dot.com.  Descramble in the standard way.&lt;br /&gt;&lt;br /&gt;The code in this blog is also free and freely available for commercial, noncommercial, academic or non-academic (if you happen to be a maraudering visigoth coder) use.  Attribute is requested as above, but not required.  Notification, as above, is also requested, but not required.&lt;br /&gt;&lt;br /&gt;Limitation of Liability:&lt;br /&gt;&lt;br /&gt;Note that, although the code and words are free and freely available for use and redistribute, no guarantee is made for any word or code sample published here.  Some non-comprehensive examples include the following: if you use this code in a missile guidance system, and that missile falls in a populated area of friendly forces and civilians, I, my words, and my code are not to be held responsible for the resulting damage to life and to property.  Or, if you implement systems published in this blog in a clustered system, and that system becomes self-aware, like Cyberdyne or the Matrix, and decides either to wipe humanity off the face of the Earth by triggering an all-out global thermonuclear war or by constructing power plants composed of the now-enslaved human population, I, my words and my code are not to be held responsible for the loss of life, freedom or property.  Or, if you use this code or the ideas explored here in a Mars rover, and it offends the space alien natives, and the descend in force, 'War of the Worlds'-style, I, my words, and my code are not to be held responsible for the resulting loss of life and damage to property.  Or, if you implement this system in a new Qbit supercomputer, and it results in either a singularly, sucking up the world Donnie Darko-style, or it results in a readjustment of space-type causing a complete quantum collapse of the universe, then I, my words, and my code are not to be held responsible for the early onset of the rapture.  The examples enumerated above serve only to illustrate that I, my words and my code may be used but any and all damage resulting from such use, no matter how small or how catastrophic, may not be held responsible for that damage, legally, financially, or otherwise.&lt;br /&gt;&lt;br /&gt;Exemption from obligation:&lt;br /&gt;&lt;br /&gt;Conversely, should you use this code, or the words of this blog, and the use results in making, earning or saving money, property or life, such as, non-exhaustively, making profit in the stock market, or gaining a strategic or tactical advantage on the battlefield, or locating 3 missing teenagers, or saving 150 sailor's lives at sea, or seizing 26 million USD-worth of illegal narcotics per month, you are under no obligation to recompense me for profits or property gained or seized, lives saved, or other benefits merited.  If possible and desired, I would like attribution in the code or words used and notification of the positive result of said use, but I also understand whims of corporate and personal desires as well as restrictions of non-disclosure agreements and concerns of national/world security, so attribution and notification are desired, as above, but not required.  The examples above illustrating exemption from your obligation are neither exhaustive, meaning any gain is covered in this exemption clause, nor are they meant to illustrate implied or real events that have occurred in the past, present or future: I make no claim as the efficacy of me, my words, or my code in any of the above illustrations, nor do I make a claim that the above illustrations are based on any past, present or future events that may or may not have occurred.&lt;br /&gt;&lt;br /&gt;Of course, I will not be uncivil, either.  And gratuities are gratefully accepted (but, as per above, neither required nor expected).  If, in gratitude, you do wish to recompense me for beneficial use of my words or code, please contact me at (scrambled) doug.at.cotilliongroup.dot.com to discuss methods of renumeration.&lt;br /&gt;&lt;br /&gt;Coverage:&lt;br /&gt;&lt;br /&gt;This license is put into effect for all entries posted by me.  All comments by me are also covered by this license.  Comments published by others are at the risk of the originators: I bear no risk nor liability of words published by others on this blog.  This license is put into effect immediately, August 2, 2008, and covers all entries from the first entry ("Trivial Monad solutions" dated May 14, 2008) to all entries and content following it until such time that it may be superseded by a new license from me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-8224486014686045212?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/8224486014686045212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=8224486014686045212' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8224486014686045212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/8224486014686045212'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/legal-disclaimer.html' title='Legal Disclaimer'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-5032998598810337604</id><published>2008-08-01T09:25:00.000-07:00</published><updated>2008-08-02T16:39:44.690-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='difference lists'/><title type='text'>Difference Lists in Haskell!</title><content type='html'>Oooh! Scrumptious!&lt;br /&gt;&lt;br /&gt;I've discovered while exploring one of my Tangents, the &lt;a href='http://comonad.com/reader/2008/a-sort-of-difference/'&gt;Comonad.Reader&lt;/a&gt;, that a member of the &lt;a href='http://www.galois.com/'&gt;Galois team&lt;/a&gt;, Don Stewart, has developed a &lt;a href='http://hackage.haskell.org/cgi-bin/hackage-scripts/package/dlist'&gt;Difference List library&lt;/a&gt; ... in Haskell.  My initial scan of the library is that it is simple, elegant and practical.  Three feathers in his cap!&lt;br /&gt;&lt;br /&gt;Excuse me while, initially, I replace in my code the 'cons then &lt;kbd&gt;reverse&lt;/kbd&gt;' list-building pattern with Don's &lt;tt&gt;DList&lt;/tt&gt;.  I also can't wait to find other applications for this type.&lt;br /&gt;&lt;br /&gt;While I'm away doing that, you can read &lt;a href='http://sigfpe.blogspot.com/'&gt;sigfpe's blog&lt;/a&gt;, particularly his &lt;a href='http://sigfpe.blogspot.com/2008/07/fibonacci-numbers-coalgebraicaly.html'&gt;clever implementation&lt;/a&gt; of the &lt;a href='http://logicaltypes.blogspot.com/2008/05/no-fibbing-getting-into-monad-groove.html'&gt;Fibonacci series&lt;/a&gt; as a &lt;a href='http://www.cs.helsinki.fi/u/ekarttun/comonad/'&gt;comonad&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-5032998598810337604?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/5032998598810337604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=5032998598810337604' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5032998598810337604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5032998598810337604'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/08/difference-lists-in-haskell.html' title='Difference Lists in Haskell!'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-255374846199078700</id><published>2008-07-31T19:45:00.000-07:00</published><updated>2009-12-10T11:06:34.616-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unification'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><category scheme='http://www.blogger.com/atom/ns#' term='monad transformers'/><category scheme='http://www.blogger.com/atom/ns#' term='maybe'/><title type='text'>Don't know; don't care: Whatever</title><content type='html'>The &lt;tt&gt;&lt;a href='http://haskell.org/onlinereport/maybe.html'&gt;Maybe&lt;/a&gt; &lt;a href='http://haskell.org/onlinereport/monad.html'&gt;Monad&lt;/a&gt;&lt;/tt&gt; type (covered in &lt;a href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html'&gt;this blog in May&lt;/a&gt;) is a practical data type in &lt;a href='http://haskell.org'&gt;Haskell&lt;/a&gt; and is used extensively.  Since it is also a &lt;tt&gt;&lt;a href='http://haskell.org/onlinereport/monad.html'&gt;MonadPlus&lt;/a&gt;&lt;/tt&gt; type, it is also immediately useful for logic programming, particularly of the semideterministic variety.  Personal, I view &lt;tt&gt;Maybe&lt;/tt&gt; as a second-order &lt;tt&gt;Bool&lt;/tt&gt;ean type, which, in itself, is a very powerful mode of expression, as &lt;a href='http://en.wikipedia.org/wiki/George_Boole'&gt;George Boole&lt;/a&gt; demonstrated.  Do yourself a favor, reread his works on algebra, or perhaps some musings from others, such as &lt;a href='http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1070.html'&gt;Dijkstra&lt;/a&gt;.  Just as &lt;a href='http://www-cs-staff.stanford.edu/~uno/'&gt;Donald Knuth&lt;/a&gt; showed that any n-tree could be transformed into an equivalent binary tree, and Paul Tarau put  that to good, &lt;em&gt;ahem&lt;/em&gt;, &lt;a href='http://logic.csci.unt.edu/tarau/research/98/jbin.html'&gt;clause and effect&lt;/a&gt;, the Boolean algebra can model many other forms of algebras ... and does, for, after all, last I checked all my calculations are reduced to boolean representations (some call them &lt;em&gt;bi&lt;/em&gt;nary digi&lt;em&gt;ts&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Yes, &lt;tt&gt;Maybe&lt;/tt&gt;'s all well and good (and for the most part, it is &amp;mdash; it's very well-suited to describe a large class of problems).  But, as a dyed-in-the-wool logic programmer, Haskell has a bit of a nagging problem capturing the concept of logic variables ... that is, a thing that either may be grounded to a particular value (which &lt;tt&gt;Maybe&lt;/tt&gt; already has when the instance is &lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;x&lt;/code&gt;) or may be free (which &lt;tt&gt;Maybe&lt;/tt&gt; does not have).  In short, the problem is with &lt;tt&gt;Nothing&lt;/tt&gt;.  And what is the problem? Values resolving to &lt;tt&gt;Nothing&lt;/tt&gt; in a monadic computation, because they represent &lt;code&gt;mzero&lt;/code&gt;, or failure, propagate throughout the entire (possibly chained) computation, forcing it to abort.  Now, under the &lt;tt&gt;Maybe&lt;/tt&gt; protocol, this is the desired result, but, when doing logic programming, it is often desirable to proceed with the computation until the value is grounded.&lt;br /&gt;&lt;br /&gt;Now, deferred computation in Haskell is not a novel concept.  In fact, there are several approaches to deferred, or nondeterministic, assignment, including &lt;a href='http://logicaltypes.blogspot.com/2008/06/haskell-rule-engine.html#unify'&gt;my own unification recipe&lt;/a&gt; as well as the &lt;a href='http://haskell.org/haskellwiki/The_Monad.Reader/Issue4/Why_Attribute_Grammars_Matter'&gt;credit card transformation&lt;/a&gt; (which the author immediately disavows).  The problem with these approaches is that they require resolution within that expression.  What we need is a data type that captures succinctly this decided or undecided state.  This we do with the &lt;tt&gt;Whatever&lt;/tt&gt; data type:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Whatever&lt;/tt&gt; x = &lt;tt&gt;Only&lt;/tt&gt; x | &lt;tt&gt;Anything&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Just like &lt;tt&gt;Mabye&lt;/tt&gt;, &lt;tt&gt;Whatever&lt;/tt&gt; can be monadic:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Functor Whatever&lt;/tt&gt; &lt;kbd&gt;where&lt;br /&gt;    fmap&lt;/kbd&gt; f (&lt;tt&gt;Only&lt;/tt&gt; x) = &lt;tt&gt;Only&lt;/tt&gt; (f x)&lt;br /&gt;    &lt;kbd&gt;fmap&lt;/kbd&gt; f &lt;tt&gt;Anything&lt;/tt&gt; = &lt;tt&gt;Anything&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;instance &lt;tt&gt;Monad Whatever&lt;/tt&gt; where&lt;br /&gt;    return&lt;/kbd&gt; x = &lt;tt&gt;Only&lt;/tt&gt; x&lt;br /&gt;    &lt;tt&gt;Only&lt;/tt&gt; x &gt;&gt;= f = f x&lt;br /&gt;    &lt;tt&gt;Anything&lt;/tt&gt; &gt;&gt;= f = &lt;tt&gt;Anything&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;You'll note that the monadic definition of &lt;tt&gt;Whatever&lt;/tt&gt; is the same as &lt;tt&gt;Maybe&lt;/tt&gt;, with the exception that &lt;tt&gt;Maybe&lt;/tt&gt; defines &lt;code&gt;fail&lt;/code&gt; on &lt;tt&gt;Nothing&lt;/tt&gt;, whereas &lt;tt&gt;Whatever&lt;/tt&gt; has no such semantics.&lt;br /&gt;&lt;br /&gt;Even though &lt;tt&gt;Whatever&lt;/tt&gt; is monadic, the interesting properties of this data type come to the fore in its more ordinary usage ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Eq&lt;/tt&gt; x &amp;rArr; &lt;tt&gt;Eq&lt;/tt&gt; (&lt;tt&gt;Whatever&lt;/tt&gt; x) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;    &lt;tt&gt;Only&lt;/tt&gt; x &amp;equiv; &lt;tt&gt;Only&lt;/tt&gt; y = x &amp;equiv; y&lt;br /&gt;    &lt;tt&gt;Anything&lt;/tt&gt; &amp;equiv; _    = &lt;tt&gt;True&lt;/tt&gt;&lt;br /&gt;    _ &amp;equiv; &lt;tt&gt;Anything&lt;/tt&gt;    = &lt;tt&gt;True&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and with that definition, simple logic puzzles, such as the following, can be constructed:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;a name='bk1'&gt;In a certain bank&lt;/a&gt; the positions of cashier, manager, and teller are held by Brown, Jones and Smith, though not necessarily respectively.&lt;br /&gt;&lt;br /&gt;The teller, who was an only child, earns the least.&lt;br /&gt;Smith, who married Brown's sister, earns more than the manager.&lt;br /&gt;&lt;br /&gt;What position does each man fill?&lt;sup&gt;&lt;small&gt;&lt;a href='#en1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;An easy enough puzzle solution to construct in Prolog, I suppose, and now given the &lt;tt&gt;Whatever&lt;/tt&gt; data type, easy enough in Haskell, too!  Starting from the universe of pairs that contain the solution ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Man&lt;/tt&gt; = &lt;tt&gt;Smith&lt;/tt&gt; | &lt;tt&gt;Jones&lt;/tt&gt; | &lt;tt&gt;Brown&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Show&lt;/tt&gt;)&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Position&lt;/tt&gt; = &lt;tt&gt;Cashier&lt;/tt&gt; | &lt;tt&gt;Manager&lt;/tt&gt; | &lt;tt&gt;Teller&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Show&lt;/tt&gt;)&lt;br /&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Sibling&lt;/tt&gt; = &lt;tt&gt;Bool&lt;/tt&gt;&lt;br /&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Ans&lt;/tt&gt; = (&lt;tt&gt;Position&lt;/tt&gt;, &lt;tt&gt;Man&lt;/tt&gt;)&lt;br /&gt;&lt;br /&gt;universe :: &lt;tt&gt;[Ans]&lt;/tt&gt;&lt;br /&gt;universe = [(pos, man) | pos &amp;larr; [&lt;tt&gt;Cashier&lt;/tt&gt;, &lt;tt&gt;Manager&lt;/tt&gt;, &lt;tt&gt;Teller&lt;/tt&gt;],&lt;br /&gt;                         man &amp;larr; [&lt;tt&gt;Smith&lt;/tt&gt;, &lt;tt&gt;Jones&lt;/tt&gt;, &lt;tt&gt;Brown&lt;/tt&gt;]]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... we restrict that universe under the constraint of the first rule ("The teller, who was an only child...") by applying "only child"ness to both the &lt;tt&gt;Teller&lt;/tt&gt; and to the &lt;tt&gt;Man&lt;/tt&gt; holding that &lt;tt&gt;Position&lt;/tt&gt; (as obtained from the fact: "... Brown's sister ..."), but, &lt;em&gt;importantly&lt;/em&gt;, abstaining from defining a sibling restriction on the other &lt;tt&gt;Position&lt;/tt&gt;s ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;-- first rule definition: The teller must be an only child&lt;br /&gt;sibling :: &lt;tt&gt;Position&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Whatever Sibling&lt;/tt&gt;&lt;br /&gt;sibling &lt;tt&gt;Teller&lt;/tt&gt; = &lt;tt&gt;Only False&lt;/tt&gt;&lt;br /&gt;sibling _      = &lt;tt&gt;Anything&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;-- fact: Brown has a sibling&lt;br /&gt;hasSibling :: &lt;tt&gt;Man&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Whatever Sibling&lt;/tt&gt;&lt;br /&gt;hasSibling &lt;tt&gt;Brown&lt;/tt&gt;  = &lt;tt&gt;Only True&lt;/tt&gt;&lt;br /&gt;hasSibling _      = &lt;tt&gt;Anything&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;-- seed: the universe constrained by the sibling relation&lt;br /&gt;seed :: &lt;tt&gt;[Ans]&lt;/tt&gt;&lt;br /&gt;seed = &lt;kbd&gt;filter&lt;/kbd&gt; (&amp;lambda;(pos, man).sibling pos &amp;equiv; hasSibling man) universe&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And, given that, we need define the rest of the rules.  The first implied rule, that each &lt;tt&gt;Position&lt;/tt&gt; is occupied by a different &lt;tt&gt;Man&lt;/tt&gt; is straightforward when implemented by the &lt;code&gt;choose&lt;/code&gt; monadic operator &lt;a href='http://logicaltypes.blogspot.com/2008/05/guarded-choice-with-monadplus.html'&gt;defined elsewhere&lt;/a&gt;, the other rule concerns the pecking order when it comes to earnings: "The teller ... earns the least" (earnings rule 1) and "Smith, ..., earns more than the manager." (earnings rule 2).  This "earnings" predicate we implement monadically, to fit in the domain of &lt;code&gt;choose&lt;/code&gt; ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;-- the earnings predicate, a suped-up &lt;kbd&gt;guard&lt;/kbd&gt;&lt;br /&gt;makesLessThan :: &lt;tt&gt;Ans&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Ans&lt;/tt&gt; &amp;rarr; &lt;tt&gt;StateT&lt;/tt&gt; [&lt;tt&gt;Ans&lt;/tt&gt;] [] ()&lt;br /&gt;&lt;br /&gt;-- earning rule 1: the teller makes less than the others&lt;br /&gt;(&lt;tt&gt;Teller&lt;/tt&gt;, _) `makesLessThan` _ = &lt;tt&gt;StateT&lt;/tt&gt; $ &amp;lambda;ans. [((), ans)]&lt;br /&gt;_ `makesLessThan` (&lt;tt&gt;Teller&lt;/tt&gt;, _) = &lt;tt&gt;StateT&lt;/tt&gt; $ &amp;lambda;_. []&lt;br /&gt;&lt;br /&gt;-- and the general ordering of earnings, allowed as long as it's&lt;br /&gt;-- different people and positions&lt;br /&gt;(pos1, man1) `makesLessThan` (pos2, man2) = &lt;tt&gt;StateT&lt;/tt&gt; $ &amp;lambda;ans.&lt;br /&gt;        &lt;kbd&gt;if&lt;/kbd&gt; pos1 &amp;equiv; pos2 &amp;or; man1 &amp;equiv; man2 &lt;kbd&gt;then&lt;/kbd&gt;  []&lt;br /&gt;        &lt;kbd&gt;else&lt;/kbd&gt; [((), ans)]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... we then complete the earnings predicate in the solution definition:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;rules :: &lt;tt&gt;StateT&lt;/tt&gt; [&lt;tt&gt;Ans&lt;/tt&gt;] [] [&lt;tt&gt;Ans&lt;/tt&gt;]&lt;br /&gt;rules = do teller@(&lt;tt&gt;Teller&lt;/tt&gt;, man1) &amp;larr; choose&lt;br /&gt;           mgr@(&lt;tt&gt;Manager&lt;/tt&gt;, man2) &amp;larr; choose&lt;br /&gt;           &lt;kbd&gt;guard&lt;/kbd&gt; $ man1 &amp;ne; man2&lt;br /&gt;           cashier@(&lt;tt&gt;Cashier&lt;/tt&gt;, man3) &amp;larr; choose&lt;br /&gt;           &lt;kbd&gt;guard&lt;/kbd&gt; (man1 &amp;ne; man3 &amp;and; man2 &amp;ne; man3)&lt;br /&gt;&lt;br /&gt;           -- we've extracted an unique person for each position,&lt;br /&gt;           -- now we define earnings rule 2: &lt;br /&gt;           --      &lt;a name='bk2'&gt;"Smith makes more than the manager"&lt;/a&gt;&lt;br /&gt;           -- using my &lt;a href='http://logicaltypes.blogspot.com/2008/06/haskell-rule-engine.html'&gt;good-enough unification&lt;/a&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#en2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; to find Smith&lt;br /&gt;&lt;br /&gt;           &lt;kbd&gt;let&lt;/kbd&gt; &lt;a name='bk3'&gt;k&lt;/a&gt; = &lt;kbd&gt;const&lt;/kbd&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#en3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;           &lt;a name='snd'&gt;&lt;kbd&gt;let&lt;/kbd&gt; smith&lt;/a&gt; = (&lt;a href='http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Arrow.html'&gt;second&lt;/a&gt; $ k &lt;tt&gt;Smith&lt;/tt&gt;)&amp;isin;[teller,mgr,cashier]&lt;br /&gt;           mgr `makesLessThan` smith&lt;br /&gt;           &lt;kbd&gt;return&lt;/kbd&gt; [teller, mgr, cashier]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and then to obtain the solution, we simply evaluate the &lt;code&gt;rules&lt;/code&gt; over the &lt;code&gt;seed&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;evalStateT rules seed&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The pivotal r&amp;ocirc;le that the &lt;tt&gt;Whatever&lt;/tt&gt; data type is in the sibling relation (defined by the involuted darts &lt;code&gt;sibling&lt;/code&gt; and &lt;code&gt;hasSibling&lt;/code&gt;).  We can abduce the derived fact that &lt;tt&gt;Brown&lt;/tt&gt; is not an only child, which, with this fact reduces the &lt;code&gt;universe&lt;/code&gt;, removing the possibility that &lt;tt&gt;Brown&lt;/tt&gt; may be a &lt;tt&gt;Teller&lt;/tt&gt; ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;universe \\ seed &amp;equiv; [(&lt;tt&gt;Teller&lt;/tt&gt;,&lt;tt&gt;Brown&lt;/tt&gt;)]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... but what about the other participants? For &lt;tt&gt;Jones&lt;/tt&gt;, when we are doing the &lt;code&gt;sibling&lt;/code&gt;/&lt;code&gt;hasSibling&lt;/code&gt; involution, we don't know his familial status (we eventually follow a chain of reasoning that leads us to the knowledge that he is an only child) and, at that point in the reasoning we don't care.  For &lt;tt&gt;Smith&lt;/tt&gt;, we never have enough information derived from the problem to determine if he has siblings, and here again, we don't care.  That is &lt;a name='bk3'&gt;the power&lt;/a&gt; that the &lt;tt&gt;Whatever&lt;/tt&gt; data type gives us,&lt;sup&gt;&lt;small&gt;&lt;a href='#en4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; we may not have enough information reachable from the expression to compute the exact value in question, but we may proceed with the computation anyway.  Unlike &lt;tt&gt;Maybe&lt;/tt&gt;'s resolution to one of the members of a type (&lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;x&lt;/code&gt;) or to no solution (&lt;tt&gt;Nothing&lt;/tt&gt;), the &lt;tt&gt;Whatever&lt;/tt&gt; data type allows the resolution (&lt;tt&gt;Only&lt;/tt&gt; &lt;code&gt;x&lt;/code&gt;), but it also &lt;a name='bk5'&gt;allows the value to remain unresolved&lt;/a&gt; within the type constraint (&lt;tt&gt;Anything&lt;/tt&gt;).&lt;sup&gt;&lt;small&gt;&lt;a href='#en5'&gt;5&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;  So, I present to you, for your logic problem-solving pleasure, the &lt;tt&gt;Whatever&lt;/tt&gt; data type.&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;Endnotes&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table border='0'&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;   &lt;td&gt;Problem 1 from &lt;a name='en1'&gt;&lt;em&gt;101 Puzzles in Thought and Logic&lt;/em&gt;&lt;/a&gt;, by C. R. Wylie, Jr. Dover Publications, Inc. New York, NY, 1957.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;   &lt;td&gt;&lt;code&gt;&lt;a name='en2'&gt;f &amp;isin; list&lt;/a&gt; = &lt;kbd&gt;head&lt;/kbd&gt; [x|x &amp;larr; list, f x &amp;equiv; x]&lt;/code&gt;  When &lt;code&gt;x&lt;/code&gt; is atomic, of course &lt;code&gt;f &amp;equiv; &lt;kbd&gt;id&lt;/kbd&gt;&lt;/code&gt;, but when &lt;code&gt;x&lt;/code&gt; is a compound term, then there are many definitions for &lt;code&gt;f&lt;/code&gt; for each data type of &lt;code&gt;x&lt;/code&gt; that satisfy the equality &lt;code&gt;f x &amp;equiv; x&lt;/code&gt; and that do not equate to &lt;kbd&gt;id&lt;/kbd&gt;.  We see one such example in the &lt;a href='#snd'&gt;code above&lt;/a&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;   &lt;td&gt;I really must define &lt;a name='en3'&gt;a library of combinators&lt;/a&gt; for Haskell, &amp;agrave; la &lt;a href='http://www.amazon.com/Mock-Mockingbird-Raymond-M-Smullyan/dp/0192801422'&gt;Smullyan's &lt;em&gt;To Mock a Mockingbird&lt;/em&gt;&lt;/a&gt;, as I've done &lt;a href='http://www.cotilliongroup.com/man/combinators-man.html'&gt;for Prolog&lt;/a&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;   &lt;td&gt;This semantic is syntactically implement in Prolog as &lt;a name='en4'&gt;anonymous logic variables&lt;/a&gt;.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk5'&gt;5&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;   &lt;td&gt;&lt;a name='en5'&gt;I find it ironic&lt;/a&gt; that &lt;tt&gt;Maybe&lt;/tt&gt; says everything about the resolution of a value, but &lt;tt&gt;Whatever&lt;/tt&gt; allows you to say &lt;tt&gt;Nothing&lt;/tt&gt; about that value's resolution.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-255374846199078700?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/255374846199078700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=255374846199078700' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/255374846199078700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/255374846199078700'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/07/dont-know-dont-care-whatever.html' title='Don&apos;t know; don&apos;t care: Whatever'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-4178167605981699014</id><published>2008-07-24T13:27:00.000-07:00</published><updated>2008-08-01T16:27:15.177-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='monad transformers'/><title type='text'>My Top-"10" Movie List</title><content type='html'>The following article is presented as a literate (literal) &lt;a href='http://haskell.org'&gt;Haskell&lt;/a&gt; program.  You can read it, and you can just as easily feed it to a Haskell interpreter, such as &lt;a href='http://haskell.org/ghc/'&gt;ghci&lt;/a&gt; or &lt;a href='http://haskell.org/hugs/'&gt;hugs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I often get into conversations with acquaintances about movies, and when a (really) good movie is mentioned, I exclaim, "That's on my Top '10' list!", because, well, it is.  After about 17 of these exclamations in a (series of) conversations, I'm often called on my assertions: "Well, what are your top 10 favorite movies then?"  So, I've been forced to show my hand.  Which language, though, to display this (ever-changing) list?  HTML, no?  XML? No, dreck, and no-no-no (been there, done that; barely survived to tell the tale).  Haskell, of course.  What follows is my top "10" movies as a program as activated data.  If you need to see the movies in something other than code, I've posted the run result: &lt;a href='http://www.cotilliongroup.com/arts/top10s.html'&gt;voil&amp;agrave;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&gt; module Movies where&lt;/pre&gt;&lt;br /&gt;The philosophy of this system, other than the fact that I count to 10 accurately, but I appear to have difficulty stopping there (just as the protagonist (?) in the movie "High Fidelity" has in counting to 5), is that I use the &lt;a href='http://www.haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-State-Lazy.html'&gt;State monad&lt;/a&gt; to control how the output of the database is formatted.  The resulting &lt;a href='http://www.cotilliongroup.com/arts/top10s.html'&gt;movie database is a tabled-HTML output&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Quite simply, the State monad contains a (modular) counter, and when my logic determines, then things happen at each cycle.&lt;br /&gt;&lt;br /&gt;The &lt;a href='http://www.haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-Reader.html'&gt;Reader transformer monad&lt;/a&gt; carries the constant of when I wish to do these things, so the net result is a State monad counter wrapped in a Reader (constant) transformer.  This article is not about the (very useful) topic of monad transformers, so I recommend the &lt;a href='http://uebb.cs.tu-berlin.de/~magr/pub/Transformers.en.html'&gt;excellent article&lt;/a&gt; that covers that material.&lt;br /&gt;&lt;pre&gt;&gt; import Control.Monad.State&lt;br /&gt;&gt; import Control.Monad.Reader&lt;br /&gt;&lt;br /&gt;&gt; data Cat a = Cat String [a]&lt;/pre&gt;&lt;br /&gt;... unfortunately, the type-class system balks at using bare or aliased types, such as string, so here I wrap String in the "S" data type and provide my HTML representation against that.&lt;br /&gt;&lt;pre&gt;&gt; type Caddy = Cat (S Int)   -- quite the cad, indeed!&lt;br /&gt;&lt;br /&gt;&gt; data S s = S s String &lt;br /&gt;&lt;br /&gt;&gt; instance Show (S s) where &lt;br /&gt;&gt;     show (S s str) = cdata str []&lt;/pre&gt;&lt;br /&gt;Not particularly happy with the cdata transformation, either, but it's a quick and dirty implementation to handle a problem of character data in the database that would muck up an HTML representation.&lt;br /&gt;&lt;pre&gt;&gt; cdata [] ans = reverse ans &lt;br /&gt;&gt; cdata (a:b) ans = cdata b ((if a == '&amp;' then 'n' else a) : ans)&lt;/pre&gt;&lt;br /&gt;The typeclass Html is a pretty printer that generates HTML from the data set.&lt;br /&gt;&lt;pre&gt;&gt; class Html a where&lt;br /&gt;&gt;    asHtml :: a &amp;rarr; ReaderT Int (State Int) String&lt;/pre&gt;&lt;br /&gt;Here, when the typeclass is given an instance of "String" (wrapped in the S data type), it pretty prints columns, wrapping every n columns were n is the constant held by the ReaderT transformer monad.&lt;br /&gt;&lt;pre&gt;&gt; instance Html (S s) where&lt;br /&gt;&gt;    asHtml x = do pre &amp;larr; prefix&lt;br /&gt;&gt;                  post &amp;larr; postfix&lt;br /&gt;&gt;                  return (pre ++ "&amp;lt;td&gt;" ++ show x&lt;br /&gt;&gt;                          ++ "&amp;lt;/td&gt;" ++ post)&lt;br /&gt;&gt;         where prefix = do idx &amp;larr; get&lt;br /&gt;&gt;                           return (if idx == 0 then "&amp;lt;tr&gt;" else "")&lt;br /&gt;&gt;               postfix = do sz &amp;larr; ask&lt;br /&gt;&gt;                            idx &amp;larr; get&lt;br /&gt;&gt;                            put ((idx + 1) `mod` sz)&lt;br /&gt;&gt;                            return (if idx + 1 == sz &lt;br /&gt;&gt;                                    then "&amp;lt;/tr&gt;\n" else "")&lt;/pre&gt;&lt;br /&gt;This is the engine control of the pretty printer. When given a category, it prints the title, resets the counter to zero, and then hands off the printing of columns to either itself (if the category (e.g. "Top 10 movies") contains categories (such as the genres)) or to the "String" printer (if the category just contains the movie list).&lt;br /&gt;&lt;pre&gt;&gt; instance Html a =&gt; Html (Cat a) where&lt;br /&gt;&gt;    asHtml (Cat title list) &lt;br /&gt;&gt;          = do rows &amp;larr; ask&lt;br /&gt;&gt;               put 0&lt;br /&gt;&gt;               cells &amp;larr; mapM asHtml list&lt;br /&gt;&gt;               rest &amp;larr; get&lt;br /&gt;&gt;               return ("\n&amp;lt;tr&gt;&amp;lt;th colspan='"&lt;br /&gt;&gt;                       ++ show rows ++ "'&gt;" ++ title&lt;br /&gt;&gt;                       ++ "&amp;lt;/th&gt;&amp;lt;/tr&gt;\n" ++ foldl (++) "" cells&lt;br /&gt;&gt;                       ++ closeCells ((rows - rest) `mod` rows))&lt;br /&gt;&gt;           where closeCells 0 = ""&lt;br /&gt;&gt;                 closeCells x = foldl &lt;br /&gt;&gt;                                (&amp;lambda;x y &amp;rarr; x ++ "&amp;lt;td&gt;&amp;amp;nbsp;&amp;lt;/td&gt;")&lt;br /&gt;&gt;                                "" [1..x]&lt;br /&gt;&gt;                                ++ "&amp;lt;/tr&gt;\n"&lt;/pre&gt;&lt;br /&gt;The database of movies follows:&lt;br /&gt;&lt;pre&gt;&gt; scifi, documentary, ferrn, romcom :: Caddy&lt;br /&gt;&gt; western, musicals, comedy :: Caddy&lt;br /&gt;&gt; horror, brit, oldies, sitcom, indie, drama :: Caddy&lt;br /&gt;&lt;br /&gt;&gt; movies :: Cat Caddy&lt;br /&gt;&gt; movies = Cat "My Top 10 Movies" &lt;br /&gt;&gt;               [scifi, ferrn, romcom, musicals, &lt;br /&gt;&gt;                comedy, indie, documentary,&lt;br /&gt;&gt;                horror, brit, sitcom, drama, oldies,&lt;br /&gt;&gt;                western, anime]&lt;br /&gt;&lt;br /&gt;&gt; anime = Cat "Animation" &lt;br /&gt;&gt;             (map (S 1) ["Emporer's New Groove", "Wallace &amp;amp; Gromit", &lt;br /&gt;&gt;                         "Shrek"])&lt;br /&gt;&gt; scifi = Cat "Science Fiction" &lt;br /&gt;&gt;             (map (S 2) ["Solaris", "Blade Runner", "Galaxy Quest",&lt;br /&gt;&gt;                         "Donnie Darko", "Fight Club"])&lt;br /&gt;&gt; ferrn = Cat "Foreign"&lt;br /&gt;&gt;             (map (S 3) ["Le Placard", "Yojimbo", "Bleu, Blanc, Rouge", &lt;br /&gt;&gt;                         "Siti no Samurai", "Sanjuro", "Eiron Shimbum", &lt;br /&gt;&gt;                         "Schultze gets the Blues", "Eat Drink Man Woman", &lt;br /&gt;&gt;                         "Legend of Drunken Master", "Shaolin Soccer", &lt;br /&gt;&gt;                         "Kung Fu (Hustle)", "Cronos"])&lt;br /&gt;&gt; romcom = Cat "Romantic Comedy" &lt;br /&gt;&gt;              (map (S 4) ["George of the Jungle", "Charade", "Bull Durham",&lt;br /&gt;&gt;                          "Bride and Prejudice", "L.A. Story",&lt;br /&gt;&gt;                          "Moonstruck", "My Big, Fat Greek Wedding", &lt;br /&gt;&gt;                          "Bullets Over Broadway", "Clueless", "Ocean's 11",&lt;br /&gt;&gt;                          "Whole Nine Yards", "Princess Bride"])&lt;br /&gt;&gt; musicals = Cat "Musical"&lt;br /&gt;&gt;                (map (S 5) ["Guys and Dolls", "Singin' in the Rain", &lt;br /&gt;&gt;                            "Mary Poppins"])&lt;br /&gt;&gt; brit = Cat "Brit"&lt;br /&gt;&gt;            (map (S 6) ["Cold Comfort Farm", "Importance of Being Earnest",&lt;br /&gt;&gt;                        "Hot Fuzz"])&lt;br /&gt;&gt; oldies = Cat "Ole Timey"&lt;br /&gt;&gt;              (map (S 7) ["O Brother, Where art Thou?",&lt;br /&gt;&gt;                          "To Have and Have Not", "Hopscotch"])&lt;br /&gt;&gt; western = Cat "Western" &lt;br /&gt;&gt;               (map (S 8) ["Shanghai Noon", "Pale Rider",&lt;br /&gt;&gt;                           "Dances with Wolves"])&lt;br /&gt;&gt; comedy = Cat "Comedy" &lt;br /&gt;&gt;              (map (S 9) ["Blazing Saddles", "Arsenic and Old Lace",&lt;br /&gt;&gt;                          "Dodgeball", "Young Frankenstein",&lt;br /&gt;&gt;                          "Harold &amp;amp; Kumar go to White Castle",&lt;br /&gt;&gt;                          "Revenge of the Pink Panther"])&lt;br /&gt;&gt; sitcom = Cat "Sitcom"&lt;br /&gt;&gt;              (map (S 10) ["Addams Family", "Addams Family Values", &lt;br /&gt;&gt;                           "State and Main", "Rushmore"])&lt;br /&gt;&gt; horror = Cat "Horror/Suspense" &lt;br /&gt;&gt;              (map (S 11) ["Jacob's Ladder", "Silence of the Lambs",&lt;br /&gt;&gt;                           "Shawn of the Dead"])&lt;br /&gt;&gt; drama = Cat "Drama" &lt;br /&gt;&gt;             (map (S 12) ["Grave of the Fireflies", "Village", "Payback",&lt;br /&gt;&gt;                          "Shadowlands", "Station Agent", "Pleasantville",&lt;br /&gt;&gt;                          "Shoot 'em up", "Searching for Bobby Fischer"])&lt;br /&gt;&gt; indie = Cat "Indies" &lt;br /&gt;&gt;             (map (S 13) ["Bagdad Cafe", "Ghost World", &lt;br /&gt;&gt;                          "Living in Oblivion", "My New Gun"])&lt;br /&gt;&gt; documentary = Cat "Documentaries" &lt;br /&gt;&gt;                   (map (S 14) ["Good Night and Good Luck",&lt;br /&gt;&gt;                                "thirty two short films about Glenn Gould",&lt;br /&gt;&gt;                                "Koyaanisqatsi", "Unzipped", "Ed Wood"])&lt;/pre&gt;&lt;br /&gt;This function calls the monadic system to print the movie database.&lt;br /&gt;&lt;pre&gt;&gt; showMovies :: Int &amp;rarr; String&lt;br /&gt;&gt; showMovies cols = "&amp;lt;table&gt;\n"&lt;br /&gt;&gt;                   ++ evalState (runReaderT (asHtml movies) cols) 0&lt;br /&gt;&gt;                   ++ "\n&amp;lt;/table&gt;\n"&lt;br /&gt;&lt;br /&gt;&gt; test = putStrLn (showMovies 3)&lt;/pre&gt;&lt;br /&gt;You can &lt;a href='http://www.cotilliongroup.com/arts/Movies.lhs'&gt;download it&lt;/a&gt; and see the embedded HTML in a code browser, such as &lt;a href='http://eclipse.org'&gt;eclipse&lt;/a&gt;.  At any rate, executing &lt;code&gt;test&lt;/code&gt; will get the above &lt;a href='http://www.cotilliongroup.com/arts/top10s.html'&gt;movie database in a tabled-HTML form&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;What's the payoff?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Ah, yes.  Well, if I had encoded my movie list in one of the currently popular metadata formats, such as HTML or XML/XSTL, then changing the number of columns per row would be prohibitively difficult with the former (HTML), and getting the metadata output as a properly formatted set of table rows would have been prohibitively difficult with the latter (XSTL).  The Haskell program demonstrates both:  you've seen how (relatively) easy it is to output the structured data as table rows of three columns per row, to change the number of columns (e.g.: to two columns per row), it's as simple as rewriting the test function to ...&lt;br /&gt;&lt;pre&gt;test = putStrLn (showMovies 2)&lt;/pre&gt;&lt;br /&gt;... paid off; or, if you prefer, &lt;a href='http://www.cotilliongroup.com/arts/top10s2.html'&gt;Q.E.D.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Alternative Implementations&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Using the Reader monad is one of the ways to pass around "global" values, defining a ("global") constant function is another, &lt;a href='http://sigfpe.blogspot.com/'&gt;sigfpe&lt;/a&gt; discusses those, as well as using the Reader &lt;a href='http://www.cs.helsinki.fi/u/ekarttun/comonad/'&gt;Comonad&lt;/a&gt;, in &lt;a href='http://sigfpe.blogspot.com/2008/06/categories-of-polynomials-and-comonadic.html'&gt;an article on comonadic plumbing&lt;/a&gt;.  I chose the Reader transformer monad instead of the Reader comonad for this article, because combining a comonad with a monad introduces arrows as the glue.  Another article will explore comonads first before we dive into the thick of monad/comonad/arrow plumbing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-4178167605981699014?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/4178167605981699014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=4178167605981699014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4178167605981699014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4178167605981699014'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/07/my-top-10-movie-list.html' title='My Top-&quot;10&quot; Movie List'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-3335943436622767599</id><published>2008-06-04T17:35:00.000-07:00</published><updated>2010-05-31T01:18:26.052-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unification'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><title type='text'>A Haskell Rule Engine</title><content type='html'>Those of you who have read other entries on this blog know that the title does not contain a (semantic) typo.  Those of you new to this discourse may wonder, "Rule Engine?  Not Haskell; Prolog! End of discussion, right?"&lt;br /&gt;&lt;br /&gt;&lt;a name='#bk1'&gt;Well, yes and no&lt;/a&gt;.&lt;sup&gt;&lt;small&gt;&lt;a href='#en1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;Prolog is nearly perfectly situated, semantically, for building rule engines.  In fact, the Prolog interpreter &lt;em&gt;is&lt;/em&gt; a rule engine, so making one's own rule engine amounts simply to adding rules (as rules are native-language constructs in Prolog) to the interpreter (which are then compiled into the Prolog system).  What could be simpler?  Well, nearly nothing, and that's why Prolog is the language of choice for these kinds of systems (and for knowledge bases, and for work-flow analysis, and for resource scheduling systems, and for ... etc).&lt;br /&gt;&lt;br /&gt;The problem, however, is the Prolog offers a little too little and a little too much -- a little too little in typing and a little too much side-effects (&lt;em&gt;&amp;agrave; la&lt;/em&gt; &lt;code&gt;assert&lt;/code&gt;, &lt;code&gt;retract&lt;/code&gt;, and the &lt;code&gt;&lt;font color='red'&gt;!&lt;/font&gt;&lt;/code&gt; (&lt;em&gt;pron:&lt;/em&gt; "red cut")) -- and this abundance (of side effects) and dearth (of typing) both seriously hamper confidence in the correctness, or provability, of the rule system.&lt;br /&gt;&lt;br /&gt;Let's take a moment to consider how a rule-based system works.  The system is fed data; it then forms a supposition from those data, and the rules contribute, to a greater or lesser extent, to proving or disproving that supposition.  Rule-based systems often, but not always, have a dynamic element to them -- rules may be added or removed (or activated or passivated) while the system is running to deal with emergent situations.  Furthermore, rule-based systems often have a collaborative element to them: it is often desirable that rule-findings (or their antithesis) affect other rules in the same or similar category.  Contribution, dynamism, and collaboration: these are the ingredients for successful rule-based systems.  For these ingredients to work with any success, however, the supposition &lt;em&gt;must&lt;/em&gt; have a well-understood structure as it is tested from rule to rule.  Furthermore, findings that contribute to the strength of the supposition must be adjoined in well-defined ways.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;em&gt;Caveat:&lt;/em&gt; if you're looking for objectivity, read Ayn Rand.  However, even though the next section is anything but even-tempered, it is indeed tempered by years of experience on real systems really in production.  YMMV&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The Prolog programmer writing the rule-based system may render the structure of the supposition either implicitly (by testing the dynamic structure of the supposition in the goals of each rule) or explicitly (by pattern matching in the head of each rule with tagged terms of the supposition).  Either approach requires uniformity, which is just a euphemism for typing.  In short, the Prolog programmer &lt;em&gt;must&lt;/em&gt; type the supposition, but the Prolog system has no built-in check guaranteeing correctness of that type from rule to rule.  This places the burden of typing on the Prolog programmer, and this often results in the programmer accidentally building an &lt;em&gt;ad hoc&lt;/em&gt; type system extension, and often poorly enforcing that discipline from rule to rule.  The result: an ill-typed supposition is allowed to pass through the rule engine generating false positives or failing to recognize real positives from the base data set.&lt;br /&gt;&lt;br /&gt;So much for the need-for-typing screed.&lt;br /&gt;&lt;br /&gt;Now, as for the side-effecting (a.k.a. "extra-logical") constructs in Prolog (&lt;code&gt;assert&lt;/code&gt;, &lt;code&gt;retract&lt;/code&gt;, and &lt;code&gt;&lt;font color='red'&gt;!&lt;/font&gt;&lt;/code&gt;), the literature is resplendent with &lt;em&gt;caveats&lt;/em&gt;, so I will leave that discussion for your discovery (which would simply be to read the latter part of chapter 1 of any introductory Prolog text).  I will add one bit of personal professional experience:  a rule-based system built on the foundation of these extra-logical constructs (each rule issued more than a few &lt;code&gt;assert&lt;/code&gt;s which then their duals later &lt;code&gt;retract&lt;/code&gt;ed &lt;em&gt;[fingers crossed]&lt;/em&gt;).  What happened when an unusual finding surfaced?  Well, what didn't happen was a felicity in the debugger, even with a complete trace it was well nigh impossible to sort out which lemmas were &lt;code&gt;assert&lt;/code&gt;ed and at what points.  Were there detritus lemmas from the previous transaction that were never &lt;code&gt;retract&lt;/code&gt;ed due to a &lt;code&gt;&lt;font color='red'&gt;!&lt;/font&gt;&lt;/code&gt; or an unexpected failure resulting in backtracking?  These questions were hard enough to answer in that system, but the difficulty was often compounded by the inconsistency between different findings on the exact same input data.  In short, if you are a Prolog programmer who uses the extra-logical features of the language to build your rule-based system, you may have something that works from time to time, but you've also sacrificed consistency and confidence in the results.  Please, &lt;a name='bk2'&gt;for my sake&lt;/a&gt;,&lt;sup&gt;&lt;small&gt;&lt;a href='#en2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; find a way to code the system relying on the &lt;a name='bk3'&gt;logical features&lt;/a&gt; of the language as the mainstay.&lt;sup&gt;&lt;small&gt;&lt;a href='#en3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;We now return to our regularly-scheduled programming...&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Haskell, being a typed and pure functional programming language, has its &lt;a name='bk4'&gt;own strengths and weaknesses&lt;/a&gt;.&lt;sup&gt;&lt;small&gt;&lt;a href='#en4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;  The type system requires the program to be well-typed and consistent ("proofs-as-types"), otherwise the program is rejected by the Haskell system.  Conversely, foundational operations of logical programming are not to be found as part of Haskell's base syntax nor semantics.  Unification?  Backtracking?  Neither are available in "plain" Haskell.  In Prolog, what are the operators for unification and backtracking?  There are none, as these concepts are fundamental parts of Prolog's semantics -- they are as invisible and as necessary as the air, permeating the entire system down to every goal in each rule clause.&lt;br /&gt;&lt;br /&gt;If not addressed, these deficiencies of plain Haskell would stop the show.  However, &lt;a href='http://logicaltypes.blogspot.com/2008/05/guarded-choice-with-monadplus.html'&gt;previous&lt;/a&gt; &lt;a href='http://logicaltypes.blogspot.com/2008/05/composing-functions-with-arrows.html'&gt;articles&lt;/a&gt; have demonstrated typed, concise, and natural representations of choice (backtracking).  So, the rest of this article will develop a rule-based system using those tools, and along the way demonstrate how "good-enough" unification may be achieved with monads in Haskell.&lt;br /&gt;&lt;br /&gt;Before diving in to building a rule-based system in Haskell, let's pause again to consider how rule findings should be captured.  Some systems are implemented where rules return a score, and the summation of all the rule findings determine if the supposition holds.  Many such systems exist using this approach.  The problem with this approach is that it makes defining the special cases (which always crop up in these kinds of systems) difficult.  For example, a special rule finding would be: "whenever these preconditions are met, then the supposition is true, no matter what other findings occur."  How does one encode this in a points-based system?  "Obviously, that rule finding is alloted enough points to tip the scales in support of the supposition," you answer.  However, this answer, although it works today, will no longer work as, inevitably, new rules are added (and old rules removed).  When this change occurs, new thresholds are set, and the value assigned to this "ultimate" rule finding no longer triggers the expected result.  Of course, one can use indirection, where the rule finding's point value is a reference to the threshold's value, but then  this introduces additional housekeeping that the "simplification" of "rule findings are points" was supposed to avoid.  These factors -- the paradigm broken (a rule finding is not a point result but a reference to one) and the additional housekeeping -- are an open invitation to introduce logic errors into the system during the maintenance phase of the system's life cycle.&lt;br /&gt;&lt;br /&gt;And, what about the rule findings that monitor the users of the rule-based system? An integral part of every rule-based system (or expert assistance system) is the monitoring of the experts using the system.  And, in every one of these kinds of systems, there are one or more experts who consistently subvert the system and there are certain experts who consistently and markedly outperform the system.  For example, in the banking industry, the system may make recommendations that the current customer move funds over $10,000.00 out of the savings account into longer term investments, but it may also observe that the current teller is consistently successful in upselling certain profitable instruments successfully (and therefore recommend awards, promotions, or raises for that teller or may recommend pulling that teller in for interviews to enhance the system with their experience and know-how).  On the other side, there may be tellers who consistently report totals that are different than what the daily transaction report shows, and so the system may recommend to managers to bring additional supervision, training, or legal action against that teller.&lt;br /&gt;&lt;br /&gt;This subversion or excellence may be unconscious, but whatever the motive, it is imperative that this expert not be notified that their activities are being monitored.  Such a rule finding ("expert in dereliction" or "expert outperforming") would, in a point-based system, result in adding 0 points, as it doesn't affect the supposition, but it does have importance elsewhere.&lt;br /&gt;&lt;br /&gt;In short, a point-based system may work for the "normal" rules, but is unsatisfactory for any real-world system that must include special cases, such as ultimatums and rules that deal with issues not concerning proof of the supposition.&lt;br /&gt;&lt;br /&gt;Well, if points are not the way to go, what about having the rule findings immediately trigger the appropriate action?  I don't know what to call that kind of application, but it certainly isn't a rule-based system.  A system such as this immediately disintegrates into incoherency.  Let's examine an example to demonstrate, e.g.: a rule-based system for surveying banking customers has a rule that runs as follows: "A male, usually wearing a red shirt, and waving a pistol is a robber; call the police."  So, under a ruling precipitates action system, the next person (male or female) who walks in wearing a red shirt (one of the triggers) would have the SWAT team come barrelling in, weapons free.  This may impact customer satisfaction and disrupt business operations.&lt;br /&gt;&lt;br /&gt;No, part of the &lt;em&gt;raison d'&amp;ecirc;tre&lt;/em&gt; of rule-based system is that first a case must be build for, or against, a supposition with findings that are either sufficient or overwhelming in number, then, only after a compelling case is built does the system render a decision or recommendation with associated actions.  The product of such systems is not only a recommendation, but also a coherent model, a "why", in support of that recommendation.&lt;br /&gt;&lt;br /&gt;Okay, rules-as-points are out, and the imperative model ("ready-fire-aim!") is out, so what is left?  The coherent model; and a very simple model is just the set of rule findings, themselves.  With those findings, the arbiter subsystem may use any method for reaching a recommendation (points or winner-take-all or dispatch or monte carlo, etc), or even change its methodology, but the rule finding process does not need to change with each change of the arbiter.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Sometimes, loose coupling is good.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;What better way to represent rule findings than as terms of a type?  We use this representation in our example rule-based system that follows (which is the poker hand classifier &lt;a href='http://logicaltypes.blogspot.com/2008/05/composing-functions-with-arrows.html'&gt;developed earlier&lt;/a&gt;).  We already have the rules for straights, flushes, straight flushes and royal flushes:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Query&lt;/tt&gt; = [&lt;tt&gt;Card&lt;/tt&gt;] &amp;rarr; [(&lt;tt&gt;Rank&lt;/tt&gt;,&lt;tt&gt;Int&lt;/tt&gt;)] &amp;rarr; &lt;tt&gt;Maybe Type&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;royalFlush :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;royalFlush hand x = straightFlush hand x &gt;&gt;= highAce&lt;br /&gt;      &lt;kbd&gt;where&lt;/kbd&gt; highAce hand = &lt;tt&gt;RoyalFlush&lt;/tt&gt; |-&lt;br /&gt;           hand &amp;equiv; &lt;tt&gt;StraightFlush&lt;/tt&gt; (&lt;tt&gt;High&lt;/tt&gt; (&lt;tt&gt;Face Ace&lt;/tt&gt;))&lt;br /&gt;&lt;br /&gt;straightFlush :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;straightFlush hand _ = (run `conjoin` sameSuit) hand &gt;&gt;=&lt;br /&gt;                       &lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;StraightFlush&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;flush :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;flush hand x = &lt;kbd&gt;let&lt;/kbd&gt; (&lt;tt&gt;HighCard&lt;/tt&gt; hc r1 r2 r3 r4) = fromJust $ highCard hand x&lt;br /&gt;               &lt;kbd&gt;in&lt;/kbd&gt;  sameSuit hand &gt;&gt; &lt;kbd&gt;return&lt;/kbd&gt; (&lt;tt&gt;Flush&lt;/tt&gt; hc r1 r2 r3 r4)&lt;br /&gt;&lt;br /&gt;straight :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;straight hand _ = run hand &gt;&gt;= &lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;Straight&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The second argument of the &lt;tt&gt;Query&lt;/tt&gt; type, which is a bag representation of the hand -- the rank of the cards and the count for each rank, was not used in the above rules, but becomes indispensable for the other rule findings, starting with the full house (3 of a kind and 2 of a kind in one hand):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;font color='red'&gt;fullHouse _ bag = let (a,3) = head bag&lt;br /&gt;                      (b,2) = head (tail bag)&lt;br /&gt;                  in  return (FullHouse (Threes a) (Twos b))&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;No, that's not right.  The &lt;kbd&gt;let&lt;/kbd&gt;-expression is not an assignment, it's an unification!  For, after all, if the hand is not a full house, then the "assignment" fails in its "pattern match", so, not only are we attempting to fix the values of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; but we are also propagating a success or truth value through that process.  Hm, the "success of an assignment", what type would that be?  Ah! Monadic, of course, and list compression compactly captures the concept of essayed assignment which we then &lt;code&gt;distill&lt;/code&gt; (my much less cumbersome name for the standard library's &lt;code&gt;listToMaybe&lt;/code&gt; function):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;fullHouse :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;fullHouse _ bag = distill [&lt;tt&gt;FullHouse&lt;/tt&gt; (&lt;tt&gt;Threes&lt;/tt&gt; a) (&lt;tt&gt;Twos&lt;/tt&gt; b)&lt;br /&gt;                                | (a,3) &amp;larr; bag, (b,2) &amp;larr; bag]&lt;/pre&gt;&lt;/blockquote&gt; &lt;br /&gt;&lt;br /&gt;It is almost criminally embarrassing on how easy this rule is to translate from the specification: "A &lt;a name='bk5'&gt;full house&lt;/a&gt; is the distillation of a hand into three &lt;code&gt;a&lt;/code&gt;'s and two &lt;code&gt;b&lt;/code&gt;'s."&lt;sup&gt;&lt;small&gt;&lt;a href='#en5'&gt;5&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;  From this understanding, the other hands fall out naturally:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;fourofakind :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;fourofakind _ bag = distill [&lt;tt&gt;FourofaKind&lt;/tt&gt; (&lt;tt&gt;Fours&lt;/tt&gt; a) (&lt;tt&gt;High&lt;/tt&gt; b) &lt;br /&gt;                                  | (a,4) &amp;larr; bag, (b,1) &amp;larr; bag]&lt;br /&gt;&lt;br /&gt;threeofakind :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;threeofakind _ bag = distill [&lt;tt&gt;ThreeofaKind&lt;/tt&gt; (&lt;tt&gt;Threes&lt;/tt&gt; a) (&lt;tt&gt;High&lt;/tt&gt; b) c&lt;br /&gt;                                  | (a,3) &amp;larr; bag, (b,1) &amp;larr; bag,&lt;br /&gt;                                    (c,1) &amp;larr; bag, b &gt; c]&lt;br /&gt;&lt;br /&gt;twopairs :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;twopairs _ bag = distill [&lt;tt&gt;TwoPair&lt;/tt&gt; (&lt;tt&gt;Twos&lt;/tt&gt; a) (&lt;tt&gt;Twos&lt;/tt&gt; b) (&lt;tt&gt;High&lt;/tt&gt; c)&lt;br /&gt;                                  | (a,2) &amp;larr; bag, (b,2) &amp;larr; bag,&lt;br /&gt;                                    a &gt; b, (c,1) &amp;larr; bag]&lt;br /&gt;&lt;br /&gt;onepair :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;onepair _ bag = distill [&lt;tt&gt;OnePair&lt;/tt&gt; (&lt;tt&gt;Twos&lt;/tt&gt; a) (&lt;tt&gt;High&lt;/tt&gt; b) c d&lt;br /&gt;                                  | (a,2) &amp;larr; bag, (b,1) &amp;larr; bag,&lt;br /&gt;                                    (c,1) &amp;larr; bag, b &gt; c,&lt;br /&gt;                                    (d,1) &amp;larr; bag, c &gt; d]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and finally there's the catch-all for the "I'd better be good at bluffing" hand:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;highCard :: &lt;tt&gt;Query&lt;/tt&gt;&lt;br /&gt;highCard hand _ = &lt;kbd&gt;let&lt;/kbd&gt; [hc,r1,r2,r3,r4] = &lt;kbd&gt;map&lt;/kbd&gt; settleRank hand&lt;br /&gt;                  &lt;kbd&gt;in  return&lt;/kbd&gt; (&lt;tt&gt;HighCard&lt;/tt&gt; (&lt;tt&gt;High&lt;/tt&gt; hc) r1 r2 r3 r4)&lt;br /&gt;&lt;br /&gt;settleRank :: &lt;tt&gt;Card&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Rank&lt;/tt&gt;&lt;br /&gt;settleRank (&lt;tt&gt;Card&lt;/tt&gt; rank _) = rank&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now that we have the rules, we need simply write the marshalling code, the rule-finding loop, and the arbiter to complete our rule engine.  &lt;br /&gt;&lt;br /&gt;The marshalling code pre-processes the hand into a bag in order to facilitate n-of-a-kind rule findings:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;let&lt;/kbd&gt; groups = group $ &lt;kbd&gt;map&lt;/kbd&gt; settleRank cards&lt;br /&gt;    cards = &lt;kbd&gt;reverse&lt;/kbd&gt; (sort hand)&lt;br /&gt;    counts = &lt;kbd&gt;map length&lt;/kbd&gt; groups&lt;br /&gt;    bag = &lt;kbd&gt;zipWith&lt;/kbd&gt; (&lt;kbd&gt;curry&lt;/kbd&gt; (first &lt;kbd&gt;head&lt;/kbd&gt;)) groups counts&lt;br /&gt;    &lt;em&gt;[...]&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The rule-finding loop applies the rules to the (processed) hand in order:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;    &lt;em&gt;[...]&lt;/em&gt;&lt;br /&gt;    rules = [royalFlush, straightFlush, fourofakind,&lt;br /&gt;             fullHouse, flush, straight, &lt;br /&gt;             threeofakind, twopairs, onepair,&lt;br /&gt;             highCard]&lt;br /&gt;    &lt;a name='bk6'&gt;findings =&lt;/a&gt; &lt;kbd&gt;map&lt;/kbd&gt; (&amp;lambda;f . f cards bag) rules&lt;sup&gt;&lt;small&gt;&lt;a href='#en6'&gt;6&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;    &lt;em&gt;[...]&lt;/em&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;And, finally, the arbiter in this case is very simple: it takes the first (highest ordered) rule-finding as the result.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;    &lt;em&gt;[...]&lt;/em&gt;&lt;br /&gt;&lt;kbd&gt;in&lt;/kbd&gt;  fromJust (msum findings)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;With that, we have built the kernel of a complete rule-based system.&lt;br /&gt;&lt;br /&gt;In this article, we demonstrated that Haskell, with standard extensions, can follow a process that constructs rules.  This process not only matches the ease and simplicity of rule-building in Prolog, but it also has the benefit that these rules in Haskell have the type-correctness that provides a stronger degree of confidence in the rule-finding results.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table border='0'&gt;&lt;br /&gt; &lt;tr&gt;&lt;th align='left' colspan='2'&gt;&lt;u&gt;End notes&lt;/u&gt;&lt;/th&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;a name='en1'&gt;I &lt;em&gt;must&lt;/em&gt; be getting older&lt;/a&gt;.  Not too long ago, my refutation would have been more emphatic ... to the tune of: "Wrong!"&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;I say &lt;a name='en2'&gt;"for my sake"&lt;/a&gt; because I'm the guy you're going to be complaining about: "All I wanted him to do is just add this one rule set to the system, and he goes off and rewrites the entire system to do it!"&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;While you're at it, &lt;a name='en3'&gt;put all your debug&lt;/a&gt; statements into &lt;a href='http://www.cotilliongroup.com/man/aspects/aspects-man.html'&gt;aspects&lt;/a&gt; (because &lt;code&gt;nl&lt;/code&gt; should not even appear in core production code much less be the most frequently called "goal" in the system) and then have a complete(ly automated) unit test suite so that additions or deletions are entirely covered by this safety net, but those are whole ('nother) discussions onto themselves.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;But why choose a &lt;a name='en4'&gt;functional programming language like Haskell&lt;/a&gt;?  If Prolog nearly fits the bill, wouldn't a well-typed logic programming language, say, &lt;a href='http://www.cs.mu.oz.au/research/mercury/'&gt;Mercury&lt;/a&gt;, or others, fair better than Haskell?  The problems with most of these languages is that they fall into the research/academic ghetto.  The user base is comprised of the language developers and maybe one or two others, and so the languages stagnate in their insularity.  Haskell, and some other languages, including Prolog itself, have garnered enough outside attention and use to grow organically beyond their inventors' control, boundaries and strictures -- these languages retain their academic foundations but also gain a set of practical, useful, tools and extensions.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk5'&gt;5&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;... &lt;a name='en5'&gt;cannot resist&lt;/a&gt; ... "or not two &lt;code&gt;&lt;font color='green'&gt;b&lt;/font&gt;&lt;/code&gt;'s" *sigh*&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk6'&gt;6&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;The &lt;a href='http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Applicative.html'&gt;Applicative style&lt;/a&gt; (see &lt;a href='http://www.soi.city.ac.uk/~ross/papers/Applicative.html'&gt;this paper&lt;/a&gt;) would have the &lt;a name='en6'&gt;list of functions&lt;/a&gt; applied to the list of arguments thusly ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;map uncurry&lt;/kbd&gt; rules &amp;lt;*&gt; [(cards, bag)]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... but I suppose that, in itself, opens up a new topic of discussion, which I will currently shunt to another day.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-3335943436622767599?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/3335943436622767599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=3335943436622767599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/3335943436622767599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/3335943436622767599'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/06/haskell-rule-engine.html' title='A Haskell Rule Engine'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-2494872623025759598</id><published>2008-05-28T12:46:00.000-07:00</published><updated>2010-05-31T21:00:30.031-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nondeterminism'/><category scheme='http://www.blogger.com/atom/ns#' term='rule-based programming'/><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><category scheme='http://www.blogger.com/atom/ns#' term='arrow'/><title type='text'>Composing functions with Arrows</title><content type='html'>The &lt;tt&gt;&lt;a href='http://haskell.org/arrows/'&gt;Arrow&lt;/a&gt;&lt;/tt&gt; class in Haskell is a generalization of the &lt;tt&gt;Monad&lt;/tt&gt; class.  Whereas a &lt;tt&gt;Monad&lt;/tt&gt; type contains a value, and therefore is often used to represent state (in that the value captures the output of a function), an  &lt;tt&gt;Arrow&lt;/tt&gt; type represents the entire function, capturing both its inputs and outputs.&lt;br /&gt;&lt;br /&gt;This is &lt;a name='bk1'&gt;very Prolog-y&lt;/a&gt;. In Prolog, there are no functions, &lt;em&gt;per se&lt;/em&gt;: the procedure's parameters (both input and output, if the procedure has any) are explicit in the declaration.&lt;sup&gt;&lt;small&gt;&lt;a href='#en1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;  It's this total control of the procedure's environment that makes writing, e.g., &lt;a href='http://www.cotilliongroup.com/man/aspects/aspects-man.html'&gt;aspects for Prolog&lt;/a&gt; a trivial exercise.&lt;br /&gt;&lt;br /&gt;With &lt;tt&gt;Arrow&lt;/tt&gt;s, Haskell, which has always been friendly to function composition, receives another way of controlling data flow and composing functions.  This topic is broad, diverse and general, and I am just starting down the path of exploring the &lt;tt&gt;Arrow&lt;/tt&gt; class, so this entry will concentrate on only one aspect of the &lt;tt&gt;Arrow&lt;/tt&gt; class, that is data flow through a composed arrow.&lt;br /&gt;&lt;br /&gt;The problem comes up often enough: one wishes to dispatch some input through different functions and then marry the results for disposition by another function (if this sounds like neural nets or circuits, that's because those systems do just that).  The usual way of going about this work is for the programmer to shepherd the data as it flows from function to function.  However, the &lt;a href='http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Arrow.html'&gt;&lt;tt&gt;Arrow&lt;/tt&gt; protocol&lt;/a&gt; provides tools to automate this shepherding.  To provide a specific example of the above described problem, we will use &lt;a href='http://projecteuler.net/index.php?section=problems&amp;id=54'&gt;problem 54&lt;/a&gt; from &lt;a href='http://projecteuler.net/'&gt;Project Euler&lt;/a&gt; to illustrate:  which hand of poker wins (with the problem statement listing the rules of what makes a hand of poker and the ranking of hands)?&lt;br /&gt;&lt;br /&gt;To see which hand wins, first the hands must be classified to their type: high card, pair, two pairs, three of a kind, straight, flush, full house, four of a kind, straight flush and royal flush.  We will concentrate on hands that are straights, flushes, straight flushes and &lt;a name='bk2'&gt;royal flushes&lt;/a&gt;.&lt;sup&gt;&lt;small&gt;&lt;a href='#en2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;br /&gt;&lt;br /&gt;Given a hand is a list of cards of the following type ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Face&lt;/tt&gt; =  &lt;tt&gt;Jack&lt;/tt&gt; | &lt;tt&gt;Queen&lt;/tt&gt; | &lt;tt&gt;King&lt;/tt&gt; | &lt;tt&gt;Ace&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Ord&lt;/tt&gt;, &lt;tt&gt;Enum&lt;/tt&gt;)&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;N&lt;/tt&gt; = &lt;tt&gt;Two&lt;/tt&gt; | &lt;tt&gt;Three&lt;/tt&gt; | &lt;tt&gt;Four&lt;/tt&gt; | &lt;tt&gt;Five&lt;/tt&gt; | &lt;tt&gt;Six&lt;/tt&gt; | &lt;tt&gt;Seven&lt;/tt&gt; | &lt;tt&gt;Eight&lt;/tt&gt;&lt;br /&gt;         | &lt;tt&gt;Nine&lt;/tt&gt; | &lt;tt&gt;Ten&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Ord&lt;/tt&gt;, &lt;tt&gt;Enum&lt;/tt&gt;)&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Rank&lt;/tt&gt; = &lt;tt&gt;N N&lt;/tt&gt; | &lt;tt&gt;Face Face&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Ord&lt;/tt&gt;)&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Suit&lt;/tt&gt; = &lt;tt&gt;Diamonds&lt;/tt&gt; | &lt;tt&gt;Clubs&lt;/tt&gt; | &lt;tt&gt;Spades&lt;/tt&gt; | &lt;tt&gt;Hearts&lt;/tt&gt; deriving &lt;tt&gt;Eq&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Card&lt;/tt&gt; = &lt;a name='bk3'&gt;&lt;tt&gt;Card Rank Suit&lt;/tt&gt;&lt;/a&gt; deriving &lt;tt&gt;Eq&lt;/tt&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#en3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and cards are typed as follows ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;HighCard&lt;/tt&gt; = &lt;tt&gt;High Rank&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Ord&lt;/tt&gt;)&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Type&lt;/tt&gt; = &lt;em&gt;[...]&lt;/em&gt;&lt;br /&gt;             | &lt;tt&gt;Straight HighCard&lt;/tt&gt;&lt;br /&gt;             | &lt;tt&gt;Flush HighCard Rank Rank Rank Rank&lt;/tt&gt;&lt;br /&gt;             &lt;em&gt;[...]&lt;/em&gt;&lt;br /&gt;             | &lt;tt&gt;StraightFlush HighCard&lt;/tt&gt;&lt;br /&gt;             | &lt;tt&gt;RoyalFlush&lt;/tt&gt; deriving (&lt;tt&gt;Eq&lt;/tt&gt;, &lt;tt&gt;Ord&lt;/tt&gt;)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and the cards are ranked in descending order, seeing if a hand is a straight is simply a check to see if all cards are a run:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;run :: &lt;tt&gt;MonadPlus&lt;/tt&gt; m &amp;rArr; [&lt;tt&gt;Card&lt;/tt&gt;] &amp;rarr; m &lt;tt&gt;HighCard&lt;/tt&gt;&lt;br /&gt;run (&lt;tt&gt;Card&lt;/tt&gt; rank _:cards) &lt;br /&gt;     = &lt;tt&gt;High&lt;/tt&gt; rank |- descending (value rank) &lt;br /&gt;                               (&lt;kbd&gt;map&lt;/kbd&gt; value cards)&lt;br /&gt;     &lt;kbd&gt;where&lt;/kbd&gt; descending _ [] = &lt;tt&gt;True&lt;/tt&gt;&lt;br /&gt;           descending x (card:t) = x - 1 &amp;equiv; card&lt;br /&gt;                                   &amp;and; descending card t&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... where the &lt;code&gt;value&lt;/code&gt; returns the value (of the rank) of the card (&lt;tt&gt;Two&lt;/tt&gt; &amp;equiv; 2, &lt;tt&gt;Three&lt;/tt&gt; &amp;equiv; 3, ..., &lt;tt&gt;King&lt;/tt&gt; &amp;equiv; 12, &lt;tt&gt;Ace&lt;/tt&gt; &amp;equiv; 13), and the &lt;code&gt;|-&lt;/code&gt; function &lt;em&gt;[pron: "implied by"]&lt;/em&gt; converts a value to its &lt;tt&gt;MonadPlus&lt;/tt&gt; equivalent based on the result of a predicate:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;(|-) :: &lt;tt&gt;MonadPlus&lt;/tt&gt; m &amp;rArr; a &amp;rarr; &lt;tt&gt;Bool&lt;/tt&gt; &amp;rarr; m a&lt;br /&gt;x |- p | p         = &lt;kbd&gt;return&lt;/kbd&gt; x&lt;br /&gt;       | &lt;kbd&gt;otherwise&lt;/kbd&gt; = mzero&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;A flush is a hand that has all cards of the same suit ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;sameSuit :: &lt;tt&gt;MonadPlus&lt;/tt&gt; m &amp;rArr; [&lt;tt&gt;Card&lt;/tt&gt;] &amp;rarr; m &lt;tt&gt;Suit&lt;/tt&gt;&lt;br /&gt;sameSuit (&lt;tt&gt;Card&lt;/tt&gt; _ suit:cards) = suit |- &lt;kbd&gt;all&lt;/kbd&gt; inSuit cards&lt;br /&gt;    &lt;kbd&gt;where&lt;/kbd&gt; inSuit (&lt;tt&gt;Card&lt;/tt&gt; _ s) = s &amp;equiv; suit&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... or in the mode of &lt;code&gt;sameSuit&lt;/code&gt; a flush is a hand where every other card has the same suit as the first card.&lt;br /&gt;&lt;br /&gt;So now we have functions that determine if a hand is a flush or if its a straight.  Now, during the discussion, you may have been wondering at the return type of these functions.  Why not simply return a truth value, as these are predicates on straights and flushes?  If these functions simply tested only for straights and flushes (mutually-) exclusively, the return type of &lt;tt&gt;Bool&lt;/tt&gt; is most appropriate, but we intent to use these tests for more than just that: we will be using these simple functions to build our tests for straight flushes and royal flushes, and their return types help in that eventuality.&lt;br /&gt;&lt;br /&gt;The strength of the &lt;tt&gt;Arrow&lt;/tt&gt; class comes into its own in the following development, as well.&lt;br /&gt;&lt;br /&gt;First off, what are straight flushes and royal flushes, conceptually?  A straight flush is a straight in the same suit with a discriminating high card (for, after all, 10&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;9&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;8&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;7&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;6&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt; beats 7&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;6&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;5&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;4&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;3&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;).  A royal flush is a straight flush with an ace as the high card.  Now it is clear that the return type of the test functions above need more information than what &lt;tt&gt;Bool&lt;/tt&gt; conveys.&lt;br /&gt;&lt;br /&gt;So, we need to process the hand through both &lt;code&gt;run&lt;/code&gt; and &lt;code&gt;sameSuit&lt;/code&gt;, obtaining positive results from both functions, and we need to retrieve the result from &lt;code&gt;run&lt;/code&gt; either to ensure the hand is a royal flush (because the high card must be an ace) or to fix the value of the straight flush.  The &lt;tt&gt;Arrow&lt;/tt&gt; protocol has function, &lt;code&gt;&amp;&amp;&amp;&lt;/code&gt; &lt;em&gt;[pron. "fan-out"]&lt;/em&gt; that splits an input and sends it off to two &lt;tt&gt;Arrow&lt;/tt&gt; types for separate processing, so to determine a straight flush we start the test with ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;run &amp;&amp;&amp; straight&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... which gives the following results (with the &lt;tt&gt;Maybe&lt;/tt&gt; type selected to represent the particular &lt;tt&gt;MonadPlus&lt;/tt&gt;):&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table border='1'&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td&gt;A&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;K&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;Q&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;J&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;10&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;code&gt;(&lt;tt&gt;Just&lt;/tt&gt; (&lt;tt&gt;Face Ace&lt;/tt&gt;), &lt;tt&gt;Just &lt;/tt&gt;(&lt;tt&gt;Suit Spades&lt;/tt&gt;))&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td&gt;A&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;K&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;Q&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;J&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;10&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;code&gt;(&lt;tt&gt;Just&lt;/tt&gt; (&lt;tt&gt;Face Ace&lt;/tt&gt;), &lt;tt&gt;Nothing&lt;/tt&gt;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td&gt;A&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;K&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;7&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;6&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;2&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;code&gt;(&lt;tt&gt;Nothing&lt;/tt&gt;, &lt;tt&gt;Just&lt;/tt&gt; (&lt;tt&gt;Suit Spades&lt;/tt&gt;))&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td&gt;Q&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;Q&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;Q&lt;img src='http://cotilliongroup.com/arts/imgs/suits/diams.png'&gt;4&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;4&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;code&gt;(&lt;tt&gt;Nothing&lt;/tt&gt;, &lt;tt&gt;Nothing&lt;/tt&gt;)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Now that we have those results (in the form of a tuple pair), we need simply to perform a logical-and over the different values to obtain a conjoined truth result and to retrieve the high card's value to determine the "blue-blooded"ness of the straight flush.&lt;br /&gt;&lt;br /&gt;That solution gives us two problems to deal with:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;I'm not aware of a logical-and operation for the &lt;tt&gt;MonadPlus&lt;/tt&gt; types; but that doesn't matter because:&lt;/li&gt;&lt;br /&gt; &lt;li&gt;We're working with two &lt;em&gt;different&lt;/em&gt; types of &lt;tt&gt;MonadPlus&lt;/tt&gt; type values anyway.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;So, I rolled my own conjunctive function, favoring the result of the run, given both tests resolve positively:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mand :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; m a &amp;rarr; m b &amp;rarr; m a&lt;br /&gt;x `mand` y = y &gt;&gt; x &gt;&gt;= &lt;kbd&gt;return&lt;/kbd&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Given the above definition of &lt;code&gt;mand&lt;/code&gt; and introducing the composition function of the &lt;tt&gt;Arrow&lt;/tt&gt; protocol, &lt;code&gt;&gt;&gt;&gt;&lt;/code&gt;, we can now write the computation that determines a straight flush and returns its high card:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;run &amp;&amp;&amp; sameSuit &gt;&gt;&gt; &lt;kbd&gt;uncurry&lt;/kbd&gt; mand&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In fact, &lt;a name='bk4'&gt;this pattern&lt;/a&gt;: &lt;code&gt;f &amp;&amp;&amp; g &gt;&gt;&gt; &lt;kbd&gt;uncurry&lt;/kbd&gt; mand&lt;/code&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#en4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt; neatly captures the logic programming paradigm of goal-seeking via conjunction, so it deserves it's own apt abstraction:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;conjoin :: &lt;tt&gt;Monad&lt;/tt&gt; m &amp;rArr; (a &amp;rarr; m b) &amp;rarr; (a &amp;rarr; m c) &amp;rarr; a &amp;rarr; m b&lt;br /&gt;conjoin f g = f &amp;&amp;&amp; g &gt;&gt;&gt; &lt;kbd&gt;uncurry&lt;/kbd&gt; mand&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, now we have the tools available to discriminate a hand's type along the straight or royal flush -- the straight flush simply returns the type with the high card value ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;straightFlush :: [&lt;tt&gt;Card&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe Type&lt;/tt&gt;&lt;br /&gt;straightFlush hand = (run `conjoin` sameSuit) hand &gt;&gt;=&lt;br /&gt;                     &lt;kbd&gt;return&lt;/kbd&gt; . &lt;tt&gt;StraightFlush&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and a royal flush is a straight flush with a guaranteed high ace:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;royalFlush :: [&lt;tt&gt;Card&lt;/tt&gt;] &amp;rarr; &lt;tt&gt;Maybe Type&lt;/tt&gt;&lt;br /&gt;royalFlush hand = straightFlush hand &gt;&gt;= highAce&lt;br /&gt;   &lt;kbd&gt;where&lt;/kbd&gt; highAce kind&lt;br /&gt;           = &lt;tt&gt;RoyalFlush&lt;/tt&gt; |- kind &amp;equiv; &lt;tt&gt;StraightFlush&lt;/tt&gt; (&lt;tt&gt;High&lt;/tt&gt; (&lt;tt&gt;Face Ace&lt;/tt&gt;))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Note the complementary r&amp;ocirc;les of &lt;code&gt;conjoin&lt;/code&gt; and &lt;code&gt;&gt;&gt;=&lt;/code&gt; &lt;em&gt;[pron. bind]&lt;/em&gt;: &lt;code&gt;conjoin&lt;/code&gt; &lt;em&gt;marries&lt;/em&gt; two truth values (emphasizing the first), and &lt;code&gt;&gt;&gt;=&lt;/code&gt; &lt;em&gt;forwards&lt;/em&gt; a truth value for disposition.  Due to the monadic nature of these functions, a false result (or failure) at any point in the computation aborts it, so these nondeterministic functions are very well-behaved: what is returned is &lt;em&gt;either&lt;/em&gt; &lt;tt&gt;Just&lt;/tt&gt; a straight flush or a royal flush if and only if every test is true along the way,  &lt;em&gt;or&lt;/em&gt; &lt;tt&gt;Nothing&lt;/tt&gt; if even a single test fails.&lt;br /&gt;&lt;br /&gt;In summary, this particular aspect of the &lt;tt&gt;Arrow&lt;/tt&gt; protocol that captures the totality of functions and simplifies the control of data flow gives a particularly powerful and flexible set of tools to the user, combining this flexibility with (&lt;tt&gt;Arrow&lt;/tt&gt;) composition and the existing &lt;tt&gt;Monad&lt;/tt&gt; and &lt;tt&gt;MonadPlus&lt;/tt&gt; facilities allows a programming style as simple, declarative and powerful as the logic-programming paradigm.&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table border='0'&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk1'&gt;1&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;a name='en1'&gt;Further distancing&lt;/a&gt; Prolog procedures from Haskell functions, the outcome of a procedure is not an "output" but its validity, or truth value -- &lt;em&gt;how very un-Haskell-y!&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk2'&gt;2&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;&lt;a name='en2'&gt;But seriously!  A royal flush?&lt;/a&gt; How many of you have every drawn that hand?  There should be some special rule for drawing a royal flush, like: you get a life-time supply of marzipan loaded into the trunk of your brand new Bentley parked at your vacation home in St. Croix.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk3'&gt;3&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;Note that in poker there is &lt;a name='en3'&gt;&lt;em&gt;no&lt;/em&gt; precedence&lt;/a&gt; of suits (unlike in other card games, like &lt;a href='http://www.acbl.org/learn/howToPlay.html'&gt;Contract Bridge&lt;/a&gt;), so &lt;tt&gt;Suit&lt;/tt&gt; &lt;em&gt;is not&lt;/em&gt; an &lt;tt&gt;Ord&lt;/tt&gt; type.  This means, that since the &lt;tt&gt;Card&lt;/tt&gt; type contains a &lt;tt&gt;Suit&lt;/tt&gt; value, it, too, &lt;em&gt;is not&lt;/em&gt; ordered ... if it were, then the situation would arise where a high card hand of 10&lt;img src='http://cotilliongroup.com/arts/imgs/suits/clubs.png'&gt;9&lt;img src='http://cotilliongroup.com/arts/imgs/suits/diams.png'&gt;... would lose to a high card hand of 10&lt;img src='http://cotilliongroup.com/arts/imgs/suits/hearts.png'&gt;6&lt;img src='http://cotilliongroup.com/arts/imgs/suits/spades.png'&gt;... which is patently &lt;em&gt;not&lt;/em&gt; within the rules of poker.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt; &lt;tr&gt;&lt;br /&gt;  &lt;td valign='top'&gt;&lt;sup&gt;&lt;small&gt;&lt;a href='#bk4'&gt;4&lt;/a&gt;&lt;/small&gt;&lt;/sup&gt;&lt;/td&gt;&lt;br /&gt;  &lt;td&gt;In fact, &lt;a name='en4'&gt;the pattern&lt;/a&gt; &lt;code&gt;foo &amp;&amp;&amp; bar &gt;&gt;&gt; &lt;kbd&gt;uncurry&lt;/kbd&gt; quux&lt;/code&gt; deserves and has &lt;a href='http://storytotell.org/articles/2007/04/08/haskell-arrows'&gt;its own article&lt;/a&gt; which very prettily describes and illustrates graphically what this pattern does.&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-2494872623025759598?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/2494872623025759598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=2494872623025759598' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2494872623025759598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/2494872623025759598'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/composing-functions-with-arrows.html' title='Composing functions with Arrows'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-5098712747568521851</id><published>2008-05-28T04:12:00.000-07:00</published><updated>2008-08-12T17:53:53.178-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monoid'/><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><title type='text'>Monoid use</title><content type='html'>I've been reading a bit about &lt;a href='http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Monoid.html'&gt;Monoids&lt;/a&gt;, which are a generalization of the &lt;tt&gt;&lt;a href='http://haskell.org/onlinereport/monad.html'&gt;MonadPlus&lt;/a&gt;&lt;/tt&gt; specialization of the &lt;tt&gt;Monad&lt;/tt&gt; class.  The generalization of &lt;tt&gt;Monoids&lt;/tt&gt; is that whereas a particular &lt;tt&gt;Monad&lt;/tt&gt; type carries some (hidden) value, a &lt;tt&gt;Monoid&lt;/tt&gt; type has no such requirement.&lt;br /&gt;&lt;br /&gt;Firstly, what is a &lt;tt&gt;Monoid&lt;/tt&gt; type?  It is something that has an empty representation (&lt;code&gt;mempty :: a&lt;/code&gt;) and has the property that allows two values to be joined (appended) to form a new value (&lt;code&gt;mappend :: a &amp;rarr; a &amp;rarr; a&lt;/code&gt;).  This protocol sounds very much like &lt;a href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html'&gt;the one for &lt;tt&gt;MonadPlus&lt;/tt&gt; types&lt;/a&gt;, doesn't it?  It does, indeed, and with good reason, for &lt;a href='http://en.wikibooks.org/wiki/Haskell/MonadPlus'&gt;every &lt;tt&gt;MonadPlus&lt;/tt&gt; type is also a &lt;tt&gt;Monoid&lt;/tt&gt; type&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;MonadPlus&lt;/tt&gt; m &amp;rArr; &lt;tt&gt;Monoid&lt;/tt&gt; (m a) &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;     mempty  = mzero&lt;br /&gt;     mappend = mplus&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;What are some examples of &lt;tt&gt;Monoid&lt;/tt&gt;?  Well, of course, the types that are &lt;tt&gt;MonadPlus&lt;/tt&gt; types, like &lt;tt&gt;Maybe&lt;/tt&gt; and specified list types (but with an important &lt;em&gt;caveat&lt;/em&gt;: the generalized list container &lt;em&gt;must&lt;/em&gt; be specialized to contain some particular type &lt;code&gt;a&lt;/code&gt;).  But besides these, &lt;tt&gt;Monoid&lt;/tt&gt; gives us more types that &lt;em&gt;do not&lt;/em&gt; fit within the &lt;tt&gt;MonadPlus&lt;/tt&gt; protocol, for example, and importantly, integrals under addition or multiplication.&lt;br /&gt;&lt;br /&gt;Ah!  So if one were, say, doing an operation with some kind of list and then doing the exact same kind of thing, but simply marking results (counting, as &lt;em&gt;[brilliantly!]&lt;/em&gt; &lt;a href='http://okmij.org/ftp/Haskell/LC_Pnum.lhs'&gt;demonstrated&lt;/a&gt; by the &lt;a href='http://www.cotilliongroup.com/man/peano-man.html'&gt;Peano series&lt;/a&gt;, is operating on integers under addition) without the &lt;tt&gt;Monoid&lt;/tt&gt; abstraction, we would need to write two separate procedures (in the infamous style of copy-and-waste, er, &lt;em&gt;-paste&lt;/em&gt;) to work with the two separate data types, but with &lt;tt&gt;Monoid&lt;/tt&gt; we can have simply one procedure working with the &lt;tt&gt;Monoid&lt;/tt&gt; type, giving us some measure of &lt;a href='http://www.cs.chalmers.se/~patrikj/poly/'&gt;polytypic&lt;/a&gt; expressiveness.  This brings us to where we were at the end of the &lt;a href='http://logicaltypes.blogspot.com/2008/05/optimizing-factorization.html'&gt;previous entry on factorization&lt;/a&gt;, where we had developed a unifying function for factorization (where its r&amp;ocirc;les changed depending on what seed value it was given: it returned the factors when given a list or returned a count of the factors when given an integer).  Recall that our helper function, &lt;code&gt;mkadder&lt;/code&gt;, needed to be supplied with a translator function for the individual values processed and a concatenator function to tally those translated values:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;showfactors x = factors x (mkAdder &lt;kbd&gt;return&lt;/kbd&gt; mplus) []&lt;br /&gt;countfactors x = factors x (mkadder (&lt;kbd&gt;const&lt;/kbd&gt; 1) (+)) 0&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The first using function, &lt;code&gt;showfactors&lt;/code&gt; seized the advantage that lists are &lt;tt&gt;MonadPlus&lt;/tt&gt; types, but the second, &lt;code&gt;countfactors&lt;/code&gt;, could not do the same because integers are not monadic (they are not (polymorphic) containers), so this function had to provide its own versions of translation and concatenation.  &lt;br /&gt;&lt;br /&gt;This problem goes away, however, since both these particular types are &lt;tt&gt;Monoid&lt;/tt&gt; types, right?  Yes, well, there's the issue of how to enforce this relation &amp;mdash; a &lt;em&gt;unspecialized&lt;/em&gt; list is &lt;em&gt;not&lt;/em&gt; a &lt;tt&gt;Monoid&lt;/tt&gt; type, &lt;em&gt;nor&lt;/em&gt; are integers, &lt;em&gt;in general&lt;/em&gt;.  For this particular case, we must demonstrate that our particular data are of the &lt;tt&gt;Monoid&lt;/tt&gt; class (a list of integer for the former and integers under addition for the latter).&lt;br /&gt;&lt;br /&gt;So, what needs to be done is that these types need to be declared instances of the &lt;tt&gt;Monoid&lt;/tt&gt;ic domain by &lt;em&gt;injected&lt;/em&gt; their values into that domain (thanks to &lt;a href='http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/cdd33c94c459ba4f#'&gt;Dirk Thierbach's explanation&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;class&lt;/kbd&gt; &lt;tt&gt;Injector&lt;/tt&gt; m &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;    inject :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; a &amp;rarr; m a&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Injector&lt;/tt&gt; [] &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;    inject x = [x]&lt;br /&gt;&lt;br /&gt;&lt;kbd&gt;instance&lt;/kbd&gt; &lt;tt&gt;Injector Sum&lt;/tt&gt; &lt;kbd&gt;where&lt;/kbd&gt;&lt;br /&gt;    inject x = &lt;tt&gt;Sum&lt;/tt&gt; 1&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The above instance declarations do just that, making an injector on generalized lists one that translates some integral value into a specified (i.e. monoidic) list and making an injector on (generalized) sums one that translates some integral value (again) into a specified (again, monoidic) sum -- in this case the value is always translated into 1, because we are summing the &lt;em&gt;number&lt;/em&gt; of factors (each factor adding 1 to the total number of factors), not the &lt;em&gt;value&lt;/em&gt; of factors.&lt;br /&gt;&lt;br /&gt;With these instances, we can now employ the protocol of &lt;tt&gt;Monoid&lt;/tt&gt; to generalize the &lt;code&gt;mkadder&lt;/code&gt; function.  Recall its definition ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mkadder :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; &lt;br /&gt;              (a &amp;rarr; b) &amp;rarr; (b &amp;rarr; b → b) → a → a → (b → b) &lt;br /&gt;mkAdder f g y z = g (&lt;kbd&gt;if&lt;/kbd&gt;   y ≡ z&lt;br /&gt;                     &lt;kbd&gt;then&lt;/kbd&gt; f y&lt;br /&gt;                     &lt;kbd&gt;else&lt;/kbd&gt; g (f y) (f z))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... where &lt;code&gt;f&lt;/code&gt; is the translation function and &lt;code&gt;g&lt;/code&gt; is the concatenation function.  So, what &lt;code&gt;mkadder&lt;/code&gt; does is to provide a concatenator for either just one of the values (if both values are the same) or for both values.&lt;br /&gt;&lt;br /&gt;Now, we add the properties of the &lt;tt&gt;Injector&lt;/tt&gt; as well as those of the &lt;tt&gt;Monoid&lt;/tt&gt; to get a new &lt;code&gt;mkadder&lt;/code&gt; function that can stand alone needing neither a translator nor a concatenator to be provided from using functions ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mkadder :: (&lt;tt&gt;Injector&lt;/tt&gt; m, &lt;tt&gt;Monoid &lt;/tt&gt;(m a), &lt;tt&gt;Integral&lt;/tt&gt; a) &amp;rArr;&lt;br /&gt;              a → a → (m a → m a) &lt;br /&gt;mkAdder y z = mappend (&lt;kbd&gt;if&lt;/kbd&gt;   y ≡ z &lt;br /&gt;                       &lt;kbd&gt;then&lt;/kbd&gt; inject y &lt;br /&gt;                       &lt;kbd&gt;else&lt;/kbd&gt; inject y `mappend` inject z))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... where the generic functions &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt; are replaced, respectively, by the &lt;code&gt;inject&lt;/code&gt; function from the &lt;tt&gt;Injector&lt;/tt&gt; class and the &lt;code&gt;mappend&lt;/code&gt; function from the &lt;tt&gt;Monoid&lt;/tt&gt; class.  Note, also that the type-relation that was unspecific in the previous version, &lt;code&gt;(a &amp;rarr; b)&lt;/code&gt;, now has an explicit relation, &lt;code&gt;(a &amp;rarr; m a)&lt;/code&gt;, thanks to the relation of the types between the &lt;tt&gt;Injector&lt;/tt&gt; and &lt;tt&gt;Monoid&lt;/tt&gt; classes.  This relationship gives us a weak equivalent of a &lt;a href='http://www.haskell.org/haskellwiki/Functional_dependencies'&gt;functional dependency&lt;/a&gt;.  With this change in place, the using functions now no longer need to specify these functions, so they, in turn, simplify to:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;showfactors x = factors x mkAdder []&lt;br /&gt;countfactors x = getSum (factors x mkadder (&lt;tt&gt;Sum&lt;/tt&gt; 0))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, if you find yourself doing the same thing to very different types, and they all are not monadic, then perhaps the monoidic form may give the generality to encode those disparate types under one solution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-5098712747568521851?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/5098712747568521851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=5098712747568521851' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5098712747568521851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/5098712747568521851'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/monoid-use.html' title='Monoid use'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-6280291319546636323</id><published>2008-05-24T15:43:00.000-07:00</published><updated>2008-08-02T17:54:33.384-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><title type='text'>Optimizing Factorization</title><content type='html'>I've been working my way through the problems hosted by &lt;a href='http://projecteuler.net/index.php?section=problems'&gt;Project Euler&lt;/a&gt;.  Usually, using a na&amp;iuml;ve approach coupled with &lt;a href='http://logicaltypes.blogspot.com/2008/05/guarded-choice-with-monadplus.html'&gt;efficient nondeterminism&lt;/a&gt; suffices (oh! don't other problem solvers wish they had the &lt;tt&gt;MonadPlus&lt;/tt&gt; in their semantics when tackling the now-trivial &lt;a href='http://projecteuler.net/index.php?section=problems&amp;id=32'&gt;pandigital&lt;/a&gt; &lt;a href='http://projecteuler.net/index.php?section=problems&amp;id=43'&gt;problems&lt;/a&gt;!), but I ran into a snag when I was factoring large &lt;a href='http://projecteuler.net/index.php?section=problems&amp;id=12'&gt;triangular&lt;/a&gt; numbers.&lt;br /&gt;&lt;br /&gt;The problem was my na&amp;iuml;vet&amp;eacute;, of course.&lt;br /&gt;&lt;br /&gt;My original version of &lt;code&gt;factors&lt;/code&gt; proceeded thusly ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;factors :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; a &amp;rarr; [a]&lt;br /&gt;factors x = filter (&amp;lambda;y . x `rem` y &amp;equiv; 0) [1..x]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... which is straightforward enough.  One can't get any simpler than: "Keep ('&lt;code&gt;filter&lt;/code&gt;') all the numbers from 1 to &lt;code&gt;x&lt;/code&gt; that divide &lt;code&gt;x&lt;/code&gt; with no &lt;code&gt;rem&lt;/code&gt;ainder"!&lt;br /&gt;&lt;br /&gt;Simple?  Yes. Na&amp;iuml;ve? Yes.  For small numbers, this factorization algorithm did just fine, even for the 384&lt;small&gt;&lt;sup&gt;th&lt;/sup&gt;&lt;/small&gt; triangle, 73920, this algorithm found the 112 factors in a blink.  The problem appeared when doing a (triangular) search along the Natural number line for an unknown, large, triangle.  The factorization algorithm is linear, and combining it with a (nearly) linear search makes the entire activity quadratic.  Twenty-six &lt;em&gt;hours&lt;/em&gt; after I began my search ("find the first triangular number with more than 500 factors") the algorithm was still going with no solution.&lt;br /&gt;&lt;br /&gt;There &lt;em&gt;must&lt;/em&gt; be a better way to go about this.  And, of course, there are &lt;a href='http://www.google.com/search?q=fast+factorization&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a'&gt;more than a few ways&lt;/a&gt;, some of which you can pay for, but none, on the top of the search tree that appeared simple enough to comprehend and to implement in a reasonable time.&lt;br /&gt;&lt;br /&gt;Fortunately, there also exists an obvious sub-linear solution:  if we are given in the linear progression &lt;code&gt;[1..x]&lt;/code&gt; at the current index, &lt;code&gt;y&lt;/code&gt;, that &lt;code&gt;&lt;font color='green'&gt;y&lt;/font&gt;&lt;/code&gt; is a factor of &lt;code&gt;x&lt;/code&gt;, then obviously ... &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;z &lt;kbd&gt;where&lt;/kbd&gt; z = x / y&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... is also a factor.  Not only that, but, since we are progressing linearly, &lt;code&gt;z&lt;/code&gt; now becomes the upper bound in the factorization algorithm.  The &lt;a href='http://en.wikipedia.org/wiki/Fixed_point_combinator'&gt;fix-point&lt;/a&gt; of the algorithm described gives us a new, much more efficient, factorization ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;factors x = factors' 2 (x, [1,x])&lt;br /&gt;     &lt;kbd&gt;where&lt;/kbd&gt; factors' y res@(top, ans) | y &amp;ge; top = ans&lt;br /&gt;                 | &lt;kbd&gt;otherwise&lt;/kbd&gt; = factors'' (x `divMod` y) y res&lt;br /&gt;           factors'' (newtop, 0) y (oldtop, ans)&lt;br /&gt;                     = factors' (succ y) (newtop, y:oldtop:ans)&lt;br /&gt;           factors'' _           y res&lt;br /&gt;                     = factors' (succ y) res&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... Much more efficient? Yes.  Self-describing? Not so much.  Also, there's now a subtle error introduced by assuming all factors are unique, for ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&amp;gt; factors 25 &amp;rarr; [5,5,1,25]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... duplicates are introduced when factoring squares.  Testing uniqueness adds its own complexity:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;factors x = factors' 2 (x, [1,x])&lt;br /&gt;     &lt;kbd&gt;where&lt;/kbd&gt; factors' y res@(top, ans) | y &amp;ge; top = ans&lt;br /&gt;                 | &lt;kbd&gt;otherwise&lt;/kbd&gt; = factors'' (x `divMod` y) y res&lt;br /&gt;           factors'' (newtop, 0) y (oldtop, ans)&lt;br /&gt;                     = factors' (succ y) (newtop, &lt;u&gt;addin y oldtop ans&lt;/u&gt;)&lt;br /&gt;           factors'' _           y res&lt;br /&gt;                     = factors' (succ y) res&lt;br /&gt;           &lt;u&gt;addin x y list&lt;/u&gt; | &lt;u&gt;x &amp;equiv y&lt;/u&gt;     &lt;u&gt;= x:list&lt;/u&gt;&lt;br /&gt;                          | &lt;u&gt;otherwise = x:y:list&lt;/u&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Complexity on top of complexity!  This goes against my grain (as well as Richard O'Keefe's as you see in the side-bar quote), but is it worth it?&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&amp;gt; sort (factors (triangle 12375)) &amp;rarr; [1,2,3,&lt;em&gt;...572 others...&lt;/em&gt;,76576500]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Yes, as the above interaction took no noticeable time, whereas before no solution was available after a day's worth of computation.  So this optimized factorization algorithm is "good enough" for the task at hand, for I did solve the problem using that algorithm.&lt;br /&gt;&lt;br /&gt;But, returning to the fix-point, which more than generalizes recursive algorithms -- it can be used to think of algorithms, &lt;em&gt;qua&lt;/em&gt; algorithms, more generally.  In this particular case, I have no desire to view every one of the 576 factors of this triangular number.  No, I simply wish to ensure that there are more than 500 factors, no matter what those factors are.  So, in the large, something like a &lt;code&gt;countfactors&lt;/code&gt; (that simply returns the number of factors, instead the list of all the factors) is more desirable.  How are we to go about writing such an algorithm?  Most coders, I regret to observe, would punt to the copy-and-paste style of coding, as the desired changed is buried deeply within the algorithm.  Not only that, but the type signature of the function varies with our alternatives: in what we've developed so far, the algorithm returns a list, but what we wish to have instead is (only one) number.&lt;br /&gt;&lt;br /&gt;Fortunately, &lt;a href='http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/89703a5aad523dc5/741042e6db413c48?lnk=gst&amp;q=state+monad+style#741042e6db413c48'&gt;Dirk Thierbach introduced&lt;/a&gt; me to this particular use of the fix-point -- we simply extract the engine of computation into an external function.  So now we have two functions that collapse into one line each ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;showfactors :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; a &amp;rarr; [a]&lt;br /&gt;showfactors x = factors x (&amp;lambda; y z ans . &lt;kbd&gt;if&lt;/kbd&gt; y &amp;equiv; z &lt;kbd&gt;then&lt;/kbd&gt; y:ans &lt;kbd&gt;else&lt;/kbd&gt; y:z:ans) []&lt;br /&gt;&lt;br /&gt;countfactors :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; a &amp;rarr; a&lt;br /&gt;countfactors x = factors x (&amp;lambda; y z ans . &lt;kbd&gt;if&lt;/kbd&gt; y &amp;equiv; z &lt;kbd&gt;then&lt;/kbd&gt; 1 + ans &lt;kbd&gt;else&lt;/kbd&gt; 2 + ans) 0&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... with &lt;code&gt;factors&lt;/code&gt; being (slightly) modified to accept the new functional argument and base case:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;factors :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; a &amp;rarr; (a &amp;rarr; a &amp;rarr; b &amp;rarr; b) &amp;rarr; b &amp;rarr; b&lt;br /&gt;factors x adder ans = factors' 2 (x, adder 1 x ans)&lt;br /&gt;       &lt;kbd&gt;where&lt;/kbd&gt; factors' y (tot, ans) | y &amp;ge; tot = ans&lt;br /&gt;                       | &lt;kbd&gt;otherwise&lt;/kbd&gt;  = factors'' (x `divMod` test) y (tot, ans)&lt;br /&gt;             factors'' (tot, 0) y (_, ans)&lt;br /&gt;                     = factors' (y+1) (tot, adder y tot ans)&lt;br /&gt;             factors'' _ _ y ans&lt;br /&gt;                     = factors' y ans&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;With this approach, the return type depends on the calling function's use and is threaded throughout the utility function, &lt;code&gt;factors&lt;/code&gt;, by the &lt;code&gt;adder&lt;/code&gt; computation engine.&lt;br /&gt;&lt;br /&gt;One final note: the &amp;lambda;-terms in both calling functions &lt;code&gt;showfactors&lt;/code&gt; and &lt;code&gt;countfactors&lt;/code&gt; are also of the same structure, so we can again perform surgery, extracting the engine from the structure:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mkAdder :: &lt;tt&gt;Integral&lt;/tt&gt; a &amp;rArr; (a &amp;rarr; b) &amp;rarr; (b &amp;rarr; b &amp;rarr; b) &amp;rarr; a &amp;rarr; a &amp;rarr; (b &amp;rarr; b) &lt;br /&gt;mkAdder f g y z = g (&lt;kbd&gt;if&lt;/kbd&gt; y &amp;equiv; z &lt;kbd&gt;then&lt;/kbd&gt; f y &lt;kbd&gt;else&lt;/kbd&gt; g (f y) (f z))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now, anyone who's been working with monads for more than an brief period will see the &lt;code&gt;b&lt;/code&gt; type as monadic and the functional type &lt;code&gt;(a &amp;rarr; b)&lt;/code&gt; as a lifting function (&lt;kbd&gt;return&lt;/kbd&gt;) and the composition function, &lt;code&gt;g&lt;/code&gt;, as monadic addition.  And, as it turns out, this concept fits very nicely with the new implementation ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;showfactors x = factors x (mkAdder &lt;kbd&gt;return&lt;/kbd&gt; mplus) []&lt;br /&gt;countfactors x = factors x (mkadder (&lt;kbd&gt;const&lt;/kbd&gt; 1) (+)) 0&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;With these new implementations, how much does &lt;code&gt;factors&lt;/code&gt; need to change?  Not one bit.  Functional purity: why can't all programming languages have this?  And with this generalization, I was able to achieve the desired result:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&amp;gt; countfactors (triangle 12375) &amp;rarr; 576&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Now it is known that both lists of some type (in this case integers) and also integers under addition are &lt;a href='http://haskell.org/ghc/docs/latest/html/libraries/base/Data-Monoid.html'&gt;monoids&lt;/a&gt;.  Given that, &lt;code&gt;mkAdder&lt;/code&gt; can be further simplified.  Also, the &lt;kbd&gt;if-then-else&lt;/kbd&gt; is easily replaced by the &lt;tt&gt;Either&lt;/tt&gt; type and proper use of &lt;a href='htpp://haskell.org/arrows'&gt;arrows&lt;/a&gt;, but these are discussions for another day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-6280291319546636323?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/6280291319546636323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=6280291319546636323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6280291319546636323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/6280291319546636323'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/optimizing-factorization.html' title='Optimizing Factorization'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-7948721671692696073</id><published>2008-05-16T17:56:00.000-07:00</published><updated>2011-04-01T07:09:45.854-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nondeterminism'/><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><title type='text'>Guarded Choice with MonadPlus</title><content type='html'>In the &lt;a href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html'&gt;previous  article&lt;/a&gt;, I introduced the &lt;tt&gt;MonadPlus&lt;/tt&gt; class and three examples of monads that allow for non-determinism in programming (&lt;tt&gt;Maybe&lt;/tt&gt; and the list data type, both of which are &lt;tt&gt;MonadPlus&lt;/tt&gt; types and &lt;tt&gt;Either&lt;/tt&gt;, which can be coerced into a &lt;tt&gt;MonadPlus&lt;/tt&gt; type).  These types were introduced, but besides showing (unexplained) examples and minimal explanation of the &lt;tt&gt;Maybe&lt;/tt&gt; lookup example, there is not much there to show how to program in a declarative nondeterministic manner.  Let's rectify that.  First, we'll show how to program nondeterministically and narrow the options down with &lt;kbd&gt;guard&lt;/kbd&gt;.  We will be using the standard nondeterministic "Hello, world!" problem, that is: solving the cryptarithmetic problem ...&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;SEND + MORE = MONEY&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;... by iteratively improving the efficiency of the solution.&lt;br /&gt;&lt;br /&gt;First up, list compression is a powerfully expressive programming technique that so naturally embodies the nondeterministic programming style that users often don't know they are programming nondeterministically.  List compression is of the form:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;[ x | &lt;em&gt;qualifiers on&lt;/em&gt; x]&lt;/code&gt;&lt;br /&gt;&lt;blockquote&gt;where &lt;code&gt;x&lt;/code&gt; represent each element of the generated list, and the qualifiers either generate or constraint values for &lt;code&gt;x&lt;/code&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Given the above definition of list compression, writing the solution for our cryptarithmetic problem becomes almost as simple as writing the problem itself:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;font color='red'&gt;[(s,e,n,d,m,o,r,e,m,o,n,e,y) | s &amp;larr; digit, e &amp;larr; digit, n &amp;larr; digit,&lt;br /&gt;                               d &amp;larr; digit, m &amp;larr; digit, o &amp;larr; digit,&lt;br /&gt;                               r &amp;larr; digit, y &amp;larr; digit,&lt;br /&gt;                               s * 1000 + e * 100 + n * 10 + d&lt;br /&gt;                               + m * 1000 + o * 100 + r * 10 + e&lt;br /&gt;                               &amp;equiv; m * 10000 + o * 1000 + n * 100&lt;br /&gt;                                  + e * 10 + y]&lt;br /&gt;   where digit = [0..9]&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Easy, but when run, we see that it's not really what we needed for the answer is ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;font color='red'&gt;[(0,0,0,0,0,0,0,0,0,0,0,0,0),(0,0,0,1,0,0,0,0,0,0,0,0,1),...]&lt;/font&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and 1153 others.  No, we wish to have &lt;code&gt;SEND + MORE = MONEY&lt;/code&gt; such that &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; aren't zero and that all the letters represented &lt;em&gt;different&lt;/em&gt; digits, not, as was in the case of the first solution, all the same digit (&lt;code&gt;0&lt;/code&gt;).  Well, whereas we humans can take some obvious constraints by implication, software must be explicit, so we need to code that &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; are &lt;em&gt;strictly&lt;/em&gt; positive (meaning, "greater than zero") and that all the letters are different from each other.  Doing that, we arrive at the more complicated, but correct, following solution ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;[(s,e,n,d,m,o,r,e,m,o,n,e,y) | s &amp;larr; digit, s &gt; 0,&lt;br /&gt;                               e &amp;larr; digit, n &amp;larr; digit, d &amp;larr; digit,&lt;br /&gt;                               m &amp;larr; digit, m &gt; 0,&lt;br /&gt;                               o &amp;larr; digit, r &amp;larr; digit, y &amp;larr; digit,&lt;br /&gt;                               different [s,e,n,d,m,o,r,y], &lt;br /&gt;                               num [s,e,n,d] + num [m,o,r,e]&lt;br /&gt;                                 &amp;equiv; num [m,o,n,e,y]]&lt;br /&gt;   &lt;kbd&gt;where&lt;/kbd&gt; digit = [0..9]&lt;br /&gt;         num = &lt;kbd&gt;foldl&lt;/kbd&gt; ((+).(*10)) 0&lt;br /&gt;         different (h:t) = diff' h t&lt;br /&gt;         diff' x [] = &lt;tt&gt;True&lt;/tt&gt;&lt;br /&gt;         diff' x lst@(h:t) = &lt;kbd&gt;all&lt;/kbd&gt; (/= x) lst &amp;&amp; diff' h t&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;A bit of explanation -- the function &lt;code&gt;num fold&lt;/code&gt;s the list of digits into a number.  Put another way ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;num [s,e,n,d] &amp;equiv; ((s * 10 + e) * 10 + n) * 10 + d&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and the function &lt;code&gt;different&lt;/code&gt;, via the helper function &lt;code&gt;diff'&lt;/code&gt;, ensures that every element of the argument list are (not surprisingly) &lt;code&gt;different&lt;/code&gt; -- a translation of &lt;code&gt;diff'&lt;/code&gt; is ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;diff' x [] = &lt;tt&gt;True&lt;/tt&gt;&lt;/code&gt; &lt;em&gt;"A list is 'different' if there is only one number"&lt;/em&gt;&lt;br /&gt;&lt;code&gt;diff' x lst@(h:t) = &lt;kbd&gt;all&lt;/kbd&gt; (&amp;ne; x) lst &amp;&amp; diff' h t&lt;/code&gt; &lt;em&gt;"A list is 'different' if one of the numbers is different than every other number in the list and if this is true for all the numbers in the list&lt;/em&gt;"&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and after a prolonged period &lt;em&gt;[434 seconds]&lt;/em&gt;, it delivers the answer:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;[(9,5,6,7,1,0,8,5,1,0,6,5,2)]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Okay! We now have the solution, so we're done, right?  Well, yes, if one has all that time to wait for a solution and is willing to do tha waiting.  However, I'm of a more impatient nature: the program &lt;em&gt;can&lt;/em&gt; be faster; the program &lt;em&gt;must&lt;/em&gt; be faster.  There are few ways to go about doing this, and they involve providing hints (sometimes answers) to help the program make better choices.  We've already done a bit of this with the constraints for both &lt;code&gt;S&lt;/code&gt; and &lt;code&gt;M&lt;/code&gt; to be positive and adding the requirement that all the letters be different digits.  So, presumably, the more hints the computer has, the better and faster it will be in solving this problem.&lt;br /&gt;&lt;br /&gt;Knowing the problem better often helps in arriving at a better solution, so let's study the problem again:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt; &lt;strong&gt;S&lt;/strong&gt;END&lt;br /&gt;&lt;u&gt;+&lt;strong&gt;M&lt;/strong&gt;ORE&lt;/u&gt;&lt;br /&gt;&lt;strong&gt;M&lt;/strong&gt;ONEY&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The first (highlighted) thing that strikes me is that in &lt;code&gt;&lt;strong&gt;M&lt;/strong&gt;ONEY&lt;/code&gt;, the &lt;code&gt;M&lt;/code&gt; is free-standing -- its value is the carry from the addition of the &lt;code&gt;S&lt;/code&gt; from &lt;code&gt;&lt;strong&gt;S&lt;/strong&gt;END&lt;/code&gt; and the &lt;code&gt;M&lt;/code&gt; from &lt;code&gt;&lt;strong&gt;M&lt;/strong&gt;ORE&lt;/code&gt;.  Well, what is the greatest value for the carry?  If we maximize everything, then the values assigned are 8 and 9, then we find the carry can at most be 1, even if there's carry over (again, of at most 1) from adding the other digits.  That means &lt;code&gt;M&lt;/code&gt;, since it is not 0, &lt;em&gt;must be&lt;/em&gt; 1.&lt;br /&gt;&lt;br /&gt;What about for &lt;code&gt;S&lt;/code&gt;, can we narrow its value?  Yes, of course.  Since &lt;code&gt;M&lt;/code&gt; is fixed to 1, &lt;code&gt;S&lt;/code&gt; must be of a value that carries 1 over to &lt;code&gt;M&lt;/code&gt;.  That means it is either 9 if there's no carry from addition of the other digits or 8 if there is.  Why?  Simple: &lt;code&gt;O&lt;/code&gt; &lt;em&gt;cannot be&lt;/em&gt; 1 (as &lt;code&gt;M&lt;/code&gt; has taken that value for itself), so it turns out that there's only one value for &lt;code&gt;O&lt;/code&gt; to be: 0!  We've fixed two values and limited one letter to one of two values, 8 or 9.  Let's provide those constraints ("hints") to the system.&lt;br /&gt;&lt;br /&gt;But before we do that, our list compression is growing larger with these additional constraints, so let's unwind into an alternate representation that allows us to view the smaller pieces individually instead of having to swallow the whole pie of the problem in one bite.  This alternative representation uses the &lt;kbd&gt;do&lt;/kbd&gt;-notation, with constraints defined by &lt;kbd&gt;guard&lt;/kbd&gt;s.&lt;br /&gt;&lt;br /&gt;A &lt;kbd&gt;guard&lt;/kbd&gt; is of the following form:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;guard&lt;/kbd&gt; :: &lt;tt&gt;MonadPlus&lt;/tt&gt; m &amp;rArr; &lt;tt&gt;Bool&lt;/tt&gt; &amp;rarr; m ()&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What does that do for us?  &lt;a href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html'&gt;Recall&lt;/a&gt; that &lt;tt&gt;MonadPlus&lt;/tt&gt; kinds have a base value (&lt;code&gt;mzero&lt;/code&gt;) representing failure and other values, so &lt;kbd&gt;guard&lt;/kbd&gt; translates the input &lt;tt&gt;Bool&lt;/tt&gt;ean constraint into either &lt;code&gt;mzero&lt;/code&gt; (failure) or into a success value.  Since the entire monadic computation is chained by &lt;code&gt;mplus&lt;/code&gt;, a failure of one test voids that entire branch (because the failure &lt;em&gt;propagates&lt;/em&gt; through the entire branch of computation).&lt;br /&gt;&lt;br /&gt;So, now we are armed with &lt;kbd&gt;guard&lt;/kbd&gt;, we rewrite the solution with added constraints in the new &lt;kbd&gt;do&lt;/kbd&gt;-notation.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;do let&lt;/kbd&gt; m = 1&lt;br /&gt;       o = 0&lt;br /&gt;   s &amp;larr; digit&lt;br /&gt;   &lt;kbd&gt;guard&lt;/kbd&gt; $ s &gt; 7&lt;br /&gt;   e &amp;larr; digit&lt;br /&gt;   n &amp;larr; digit&lt;br /&gt;   d &amp;larr; digit&lt;br /&gt;   r &amp;larr; digit&lt;br /&gt;   y &amp;larr; digit&lt;br /&gt;   &lt;kbd&gt;guard&lt;/kbd&gt; $ different [s,e,n,d,m,o,r,y]&lt;br /&gt;   &lt;kbd&gt;guard&lt;/kbd&gt; $ num [s,e,n,d] + num [m,o,r,e] &amp;equiv; num [m,o,n,e,y]&lt;br /&gt;   &lt;kbd&gt;return&lt;/kbd&gt; (s,e,n,d,m,o,r,e,m,o,n,e,y)&lt;br /&gt;        &lt;kbd&gt;where&lt;/kbd&gt; digit = [2..9]&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Besides the obvious structural difference from the initial simple solution, we've introduced some other new things --&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When fixing a value, we use the &lt;kbd&gt;let&lt;/kbd&gt;-construct.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;As we've &lt;em&gt;grounded&lt;/em&gt; &lt;code&gt;M&lt;/code&gt; and &lt;code&gt;O&lt;/code&gt; to 1 and 0 respectively, we've eliminated those options from the &lt;code&gt;digit&lt;/code&gt; list.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Since the &lt;kbd&gt;do&lt;/kbd&gt;-notation works with monads in general (it's not restricted to lists only), we need to make explicit our result.  We do that with the &lt;kbd&gt;return&lt;/kbd&gt; function at the end of the block.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;What do these changes buy us?&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;[(9,5,6,7,1,0,8,5,1,0,6,5,2)]&lt;/code&gt; &lt;em&gt;returned in 0.4 seconds&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;One thing one learns quickly when doing logic, nondeterministic, programming is that the sooner a choice is settled correctly, the better.  By fixing the values of &lt;code&gt;M&lt;/code&gt; and &lt;code&gt;O&lt;/code&gt; we entirely eliminate two lines of inquiry but also eliminate two options from all the other following choices, and by refining the &lt;kbd&gt;guard&lt;/kbd&gt; for &lt;code&gt;S&lt;/code&gt; we eliminate all but two options when generating its value.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;em&gt;In nondeterministic programming, elimination is good!&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, we're done, right?  Yes, for enhancing performance, once we're in the sub-second territory, it becomes unnecessary for further optimizations.  So, in that regard, we are done.  But there is some unnecessary redundancy in the above code from a logical perspective -- once we generate a value, we know that we are not going to be generating it again.  We know this, but &lt;code&gt;&lt;font color='green'&gt;digit&lt;/font&gt;&lt;/code&gt;, being the &lt;a href='http://www.randomhacks.net/articles/2005/10/11/amb-operator'&gt;&lt;code&gt;amb&lt;/code&gt; operator&lt;/a&gt; doesn't, regenerating that value, then correcting that discrepancy only later in the computation when it encounters the &lt;code&gt;different &lt;kbd&gt;guard&lt;/kbd&gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;We need the computation to work a bit more like we do, it needs to remember what it already chose and not choose that value again.  We've already use &lt;em&gt;memoization&lt;/em&gt; when we implemented the &lt;a href='http://logicaltypes.blogspot.com/2008/05/no-fibbing-getting-into-monad-groove.html'&gt;Fibonacci&lt;/a&gt; sequence and the &lt;a href='http://logicaltypes.blogspot.com/2008/05/oh-my-acking-monad.html'&gt;Ackermann&lt;/a&gt; function with the &lt;tt&gt;State&lt;/tt&gt; monad; so let's incorporate that into our generator here.&lt;br /&gt;&lt;br /&gt;What we need is for our &lt;code&gt;amb&lt;/code&gt; operator to select from the pool of digits, but when it does so, it &lt;em&gt;removes&lt;/em&gt; that selected value from the pool.  In a logic programming language, such as Prolog, this is &lt;a href='http://www.cotilliongroup.com/arts/DCG.html'&gt;accomplished easily enough&lt;/a&gt; as nondeterminism and memoization (via difference lists) are part of the language semantics.  A clear way of dissecting this particular problem was presented to me by Dirk Thierbach in a &lt;a href='http://groups.google.com/group/comp.lang.haskell/browse_thread/thread/95151ab5e0326c13/2a109ee97817f42c?lnk=gst&amp;q=splits+delete#2a109ee97817f42c'&gt;forum post&lt;/a&gt; on &lt;a href='http://groups.google.com/group/comp.lang.haskell/topics'&gt;comp.lang.haskell&lt;/a&gt;, so I present his approach in full:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I need both state and nondeterminism, so I have to combine the state monad and the list monad. This means I need a monad transformer and a monad (you need to have seen this before, but if you have once, it's easy to remember).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The state itself also has to be a list (of candidates).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;So the final monad has type &lt;code&gt;&lt;tt&gt;StateT&lt;/tt&gt; [a] [] b&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I need some function to nondeterministically pick a candidate. This function should also update the state.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Played around a short time with available functions, didn't get anywhere.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Decided I need to go to the "bare metal".&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Expanded &lt;code&gt;&lt;tt&gt;StateT&lt;/tt&gt; [a] [] a&lt;/code&gt; into &lt;code&gt;[a] &amp;rarr; [(a,[a])]&lt;/code&gt;, then it was obvious what &lt;code&gt;choose&lt;/code&gt; should do.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Decided the required functionality "split a list into one element and rest, in all possible ways" was general enough to deserve its own function.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Wrote it down, in the first attempt without accumulator.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Wrote it down again, this time using an accumulator. &lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;With this approach presented, writing the implementation simply follows the type declaration:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;splits :: &lt;tt&gt;Eq&lt;/tt&gt; a &amp;rArr; [a] &amp;rarr; [(a, [a])]&lt;br /&gt;splits list = list &gt;&gt;= &amp;lambda;x . &lt;kbd&gt;return&lt;/kbd&gt; (x, delete x list)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Although, please do note, this implementation differs significantly from Dirk's, they both accomplish the same result.  Now we lift this computation into the &lt;tt&gt;State&lt;/tt&gt; monad &lt;em&gt;transformer&lt;/em&gt; (transformers are a topic covered &lt;a href='http://uebb.cs.tu-berlin.de/~magr/pub/Transformers.en.html'&gt;much better elsewhere&lt;/a&gt;) ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;choose :: &lt;tt&gt;StateT&lt;/tt&gt; [a] [] a&lt;br /&gt;choose = &lt;tt&gt;StateT&lt;/tt&gt; $ &amp;lambda;s . splits s&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and then replace the (forgetful) &lt;code&gt;digit&lt;/code&gt; generator with the (memoizing) &lt;code&gt;choose&lt;/code&gt; (which then eliminates the need for the &lt;code&gt;different &lt;kbd&gt;guard&lt;/kbd&gt;&lt;/code&gt;) to obtain the same result with a slight savings of time &lt;em&gt;[the result returned in 0.04 seconds]&lt;/em&gt;.   By adding these two new functions and lifting the nondeterminism into the &lt;tt&gt;StateT&lt;/tt&gt; we not only saved an imperceptibly few sub-seconds (my view is optimizing performance on sub-second computations is silly), but, importantly, we eliminated more unnecessary branches at the nondeterministic choice-points.&lt;br /&gt;&lt;br /&gt;In summary, this entry has demonstrated how to program with choice using the &lt;tt&gt;MonadPlus&lt;/tt&gt; class.  We started with a simple example that demonstrated (na&amp;iuml;ve) nondeterminism, then improved on that example by pruning branches and options with the &lt;kbd&gt;guard&lt;/kbd&gt; helper function.  Finally, we incorporated the technique of &lt;em&gt;memoization&lt;/em&gt; here that we exploited to good effect in other computational efforts to prune away redundant selections.  The end result was a program that demonstrated declarative nondeterministic programming not only fits in the (monadic) idiom of functional program but also provides solutions efficiently and within acceptable performance measures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-7948721671692696073?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/7948721671692696073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=7948721671692696073' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7948721671692696073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/7948721671692696073'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/guarded-choice-with-monadplus.html' title='Guarded Choice with MonadPlus'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-4297965994465507927</id><published>2008-05-14T15:31:00.000-07:00</published><updated>2008-08-02T18:42:49.440-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monadplus'/><category scheme='http://www.blogger.com/atom/ns#' term='maybe'/><title type='text'>Choice with Monads: List, Maybe, Either</title><content type='html'>We've seen up to now what monads are and how they can be useful in simple ways, such as for heavy lifting on recursive addition.  So, monads are useful for housekeeping when you have more work than a computer could handle in a straightforward manner.  This work is called &lt;em&gt;deterministic&lt;/em&gt;, meaning that the computation occurs in only one way.  As we have seen, monads can be helpful with this kind of computation.  But monads can be helpful with &lt;em&gt;nondeterministic&lt;/em&gt; computations, or computations that proceed along multiple possible paths, as we shall see.&lt;br /&gt;&lt;br /&gt;Haskell comes with three kinds of monads that have been used specifically for nondeterministic computation: the &lt;tt&gt;&lt;a href='#maybe'&gt;Maybe&lt;/a&gt;&lt;/tt&gt; monad, the &lt;a href='#list'&gt;list data type&lt;/a&gt; and, a new one, the &lt;tt&gt;&lt;a href='#either'&gt;Either&lt;/a&gt;&lt;/tt&gt; monad. &lt;br /&gt;&lt;br /&gt;We saw the first one &lt;a href='http://logicaltypes.blogspot.com/2008/05/no-fibbing-getting-into-monad-groove.html'&gt;in the previous post&lt;/a&gt;: the &lt;tt&gt;&lt;a name='maybe'&gt;Maybe&lt;/a&gt;&lt;/tt&gt; monad.  This monad type has two instances: &lt;tt&gt;Nothing&lt;/tt&gt; and &lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;x&lt;/code&gt; (where &lt;code&gt;x&lt;/code&gt; is the specific value of the computation).  The &lt;tt&gt;Maybe&lt;/tt&gt; monad is illustrated by the two dialogues below:&lt;br /&gt;&lt;br /&gt;&lt;table border='0'&gt;&lt;tr&gt;&lt;td align='center' colspan='2'&gt;&lt;em&gt;Scenario 1&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Waiter:&lt;/td&gt; &lt;td&gt;&lt;em&gt;How is the pork chop, can I get you anything to go with that?&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Custamah:&lt;/td&gt; &lt;td&gt;&lt;em&gt;Oh, &lt;tt&gt;Nothing&lt;/tt&gt; for me, thanks.&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Waiter:&lt;/td&gt;&lt;td&gt;&lt;em&gt;Wonderful, enjoy your meal.&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr&gt;&lt;td colspan='2'&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td colspan='2' align='center'&gt;&lt;em&gt;Scenario 2&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td colspan='2'&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Waiter:&lt;/td&gt;&lt;td&gt;&lt;em&gt;How is the pork chop, can I get you anything to go with it?&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Custamah:&lt;/td&gt;&lt;td&gt;&lt;em&gt;Oh, &lt;tt&gt;Just&lt;/tt&gt; a small bowl of applesauce, please?&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;Waiter:&lt;/td&gt;&lt;td&gt;&lt;em&gt;Sure, I'll bring that right out.&lt;/em&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;The waiter in the above two scenarios doesn't know exactly what the customer will want, but that waiter is pretty sure the customer will ask for &lt;tt&gt;Nothing&lt;/tt&gt; or for &lt;tt&gt;Just&lt;/tt&gt; something, and these options describe the &lt;tt&gt;Maybe&lt;/tt&gt; monad type.&lt;br /&gt;&lt;br /&gt;Another example of this kind of monad is the list data type.  But whereas the &lt;tt&gt;Maybe&lt;/tt&gt; monad allows two options (the answer or failure), the list data type (a monad) allows multiple answers (including no answers, which is represented by the empty list).  These kinds of monads form a protocol called the &lt;tt&gt;MonadPlus&lt;/tt&gt; class,  just as the more general monad data types form the more general protocol of the &lt;tt&gt;Monad&lt;/tt&gt; class, and just like regular monads, conform to a set of laws.&lt;br /&gt;&lt;br /&gt;First, let us specify and explain what the &lt;tt&gt;MonadPlus&lt;/tt&gt; protocol is.  All &lt;tt&gt;MonadPlus&lt;/tt&gt; types must have the following two properties defined:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;mzero :: m a&lt;/code&gt; &amp;mdash; the base, or usually interpreted as fail, value; and,&lt;br /&gt;&lt;code&gt;mplus :: m a &amp;rarr; m a &amp;rarr; m a&lt;/code&gt; &amp;mdash; a function that chooses a success value when offered two values&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;For the &lt;tt&gt;Maybe MonadPlus&lt;/tt&gt; type the above properties are defined as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mzero = &lt;tt&gt;Nothing&lt;br /&gt;Nothing&lt;/tt&gt; `mplus` b = b&lt;br /&gt;a       `mplus` b = a&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In other words, &lt;tt&gt;Nothing&lt;/tt&gt; is the failure case, and &lt;code&gt;mplus&lt;/code&gt; tries to choose a non-&lt;tt&gt;Nothing&lt;/tt&gt; value (roughly: "If &lt;code&gt;a&lt;/code&gt; is &lt;tt&gt;Nothing&lt;/tt&gt;, pick &lt;code&gt;b&lt;/code&gt;; &lt;kbd&gt;otherwise&lt;/kbd&gt; pick &lt;code&gt;a&lt;/code&gt;."  Here's a question for you: what happens when both &lt;code&gt;a&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;b&lt;/code&gt; are &lt;tt&gt;Nothing&lt;/tt&gt;, and for what reason?)  Note the interesting semantics of &lt;code&gt;mplus&lt;/code&gt; &amp;mdash; it is not at all addition, as we expect, for:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;tt&gt;Just&lt;/tt&gt; 3 `mplus` &lt;tt&gt;Just&lt;/tt&gt; 4 = &lt;tt&gt;Just&lt;/tt&gt; 3&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href='http://logicaltypes.blogspot.com/2008/05/trivial-monad-solutions.html'&gt;Recall&lt;/a&gt; that if we wish to do monadic addition, we need to define such an operator.  &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;madd :: (&lt;tt&gt;Monad&lt;/tt&gt; m, &lt;tt&gt;Num&lt;/tt&gt; a) &amp;rArr; m a &amp;rarr; m a &amp;rarr; m a&lt;br /&gt;madd = liftM2 (+)&lt;br /&gt;&lt;tt&gt;Just&lt;/tt&gt; 3 `madd` &lt;tt&gt;Just&lt;/tt&gt; 4 = &lt;tt&gt;Just&lt;/tt&gt; 7&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, now &lt;code&gt;madd&lt;/code&gt; has the triple meaning here: it &lt;em&gt;is not&lt;/em&gt; &lt;code&gt;mplus&lt;/code&gt; (which &lt;em&gt;is not&lt;/em&gt; addition), it &lt;em&gt;is&lt;/em&gt; addition for monads containing numbers, and it either heightens awareness or annoys the cause of "&lt;a href='http://www.madd.org/'&gt;MADD&lt;/a&gt;".  Got all that?&lt;br /&gt;&lt;br /&gt;The &lt;tt&gt;Maybe&lt;/tt&gt; type has a special handler, called &lt;kbd&gt;maybe&lt;/kbd&gt;.  Its type signature is:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;maybe&lt;/kbd&gt; :: b &amp;rarr; (a &amp;rarr; b) &amp;rarr; &lt;tt&gt;Maybe&lt;/tt&gt; a &amp;rarr; b&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;What does this function do?  Well, we've already seen it in action with the monadic &lt;a href='http://logicaltypes.blogspot.com/2008/05/oh-my-acking-monad.html'&gt;Ackermann&lt;/a&gt; and &lt;a href='http://logicaltypes.blogspot.com/2008/05/no-fibbing-getting-into-monad-groove.html'&gt;Fibonacci&lt;/a&gt; solutions.  One can read the arguments from right to left, to get the feel of an if-then-else:  &lt;u&gt;if&lt;/u&gt; the last argument is &lt;tt&gt;Just&lt;/tt&gt; &lt;code&gt;a&lt;/code&gt;, &lt;u&gt;then&lt;/u&gt; pass &lt;code&gt;a&lt;/code&gt; to the second argument (which is a function that converts an &lt;code&gt;a&lt;/code&gt; to the proper return type); &lt;u&gt;else&lt;/u&gt; execute the first argument.  A very compact and useful function when working with &lt;tt&gt;Maybe&lt;/tt&gt; types.&lt;br /&gt;&lt;br /&gt;The second most commonly used data type used for non-deterministic computation is the &lt;a name='list'&gt;list&lt;/a&gt; &lt;tt&gt;MonadPlus&lt;/tt&gt; data type.  It has an interesting variation from the &lt;tt&gt;Maybe&lt;/tt&gt; definition:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;mzero = []&lt;br /&gt;mplus = (++)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In other words, the empty list (&lt;code&gt;[]&lt;/code&gt;) is the base (failure) case, and &lt;code&gt;mplus&lt;/code&gt; here actually is addition ('concatenation', to be technically correct); addition, that is, in the list-sense.  But it all works out, particularly when it comes to the base cases, for:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;[3] `mplus` [] = [3]&lt;br /&gt;&lt;tt&gt;Just&lt;/tt&gt; 3 `mplus` &lt;tt&gt;Nothing&lt;/tt&gt; = &lt;tt&gt;Just&lt;/tt&gt; 3&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;But, on the other hand, &lt;code&gt;mplus&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; different when handling non-base cases for the &lt;tt&gt;Maybe&lt;/tt&gt; and list monad types, for:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;[3] `mplus` [4] = [3, 4]&lt;br /&gt;&lt;tt&gt;Just&lt;/tt&gt; 3 `mplus` &lt;tt&gt;Just&lt;/tt&gt; 4 = &lt;tt&gt;Just&lt;/tt&gt; 3&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;But this difference is consistent with the different types: the list monad allows for multiple solutions, whereas the &lt;tt&gt;Maybe&lt;/tt&gt; monad allows only one.&lt;br /&gt;&lt;br /&gt;The list data type has too many special functions associated with it to review in this post.  I recommend a review of the &lt;a href='http://haskell.org/onlinereport/standard-prelude.html#preludelist'&gt;Haskell online report&lt;/a&gt; to get a taste of list's rich functionality, and then read &lt;a href='http://www.randomhacks.net/articles/2007/03/12/monads-in-15-minutes'&gt;Eric Kidd's post on backtracking with monads&lt;/a&gt; for some insights into using list monads in nondeterministic programming.&lt;br /&gt;&lt;br /&gt;The third data type that is used, albeit less frequently, for non-deterministic computation is the &lt;tt&gt;&lt;a name='either'&gt;Either&lt;/a&gt;&lt;/tt&gt; data type.  It's structure is as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;data &lt;tt&gt;Either&lt;/tt&gt; a b = &lt;tt&gt;Left&lt;/tt&gt; a | &lt;tt&gt;Right&lt;/tt&gt; b&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The way &lt;tt&gt;Either&lt;/tt&gt; operates is that it offers a mutually-exclusive choice.  For example, little Isabel sits to my &lt;tt&gt;Left&lt;/tt&gt; and her at&amp;eacute; Elena Marie sits to my &lt;tt&gt;Right&lt;/tt&gt;, so at 4 p.m. I must choose &lt;tt&gt;Either&lt;/tt&gt; one to serve tea first: &lt;tt&gt;Left Isabel&lt;/tt&gt; or &lt;tt&gt;Right ElenaMarie&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;The interesting distinction of the &lt;tt&gt;Either&lt;/tt&gt; monad to &lt;tt&gt;MonadPlus&lt;/tt&gt; types such as the list data type and the &lt;tt&gt;Maybe&lt;/tt&gt; monad is that both options are weighed equally, or, more to the point, neither is considered to be the base case.  This means that &lt;tt&gt;Either&lt;/tt&gt;, &lt;em&gt;qua&lt;/em&gt; &lt;tt&gt;Either&lt;/tt&gt;, is not in the &lt;tt&gt;MonadPlus&lt;/tt&gt; class.  With this &lt;em&gt;caveat&lt;/em&gt;, can the &lt;tt&gt;Either&lt;/tt&gt; type be used for non-deterministic computation? &lt;a href='http://storytotell.org/articles/2007/04/08/haskell-arrows'&gt;Yes, absolutely!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Not only can the &lt;tt&gt;Either&lt;/tt&gt; type be used in its basic monadic form, but it also can be coerced into the &lt;tt&gt;MonadPlus&lt;/tt&gt; class.  How? It's simple, really.  By simply choosing one of the branches to be the base (the Haskell library designers chose &lt;tt&gt;Left&lt;/tt&gt;), the &lt;tt&gt;Either&lt;/tt&gt; type now conforms to that protocol.  The convention assigns the error message (a &lt;tt&gt;String&lt;/tt&gt;) to the &lt;tt&gt;Left&lt;/tt&gt; and the value sought is assigned to the &lt;tt&gt;Right&lt;/tt&gt; one.  This rather reduces &lt;tt&gt;Either&lt;/tt&gt; to a glorified, error-handling, &lt;tt&gt;Maybe&lt;/tt&gt;, and that is how it is used in every-day Haskell code for the most part.&lt;br /&gt;&lt;br /&gt;The &lt;tt&gt;Either&lt;/tt&gt; monad also has a special handler, &lt;kbd&gt;either&lt;/kbd&gt;, with the type signature of:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;either&lt;/kbd&gt; :: (a &amp;rarr; c) &amp;rarr; (b &amp;rarr; c) &amp;rarr; &lt;tt&gt;Either&lt;/tt&gt; a b &amp;rarr; c&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This function is in the same vein as the &lt;tt&gt;Maybe&lt;/tt&gt; handler, but complicated by the fact that &lt;kbd&gt;maybe&lt;/kbd&gt; has only one (success) type to handle, whereas this function has two possible types it deals with &amp;mdash; &lt;kbd&gt;either&lt;/kbd&gt;'s type translates as: if the answer from the third argument (&lt;tt&gt;Either&lt;/tt&gt; &lt;code&gt;a b&lt;/code&gt;) is &lt;tt&gt;Left&lt;/tt&gt; &lt;code&gt;a&lt;/code&gt;, then feed &lt;code&gt;a&lt;/code&gt; to the first argument (a function that converts the input value of type &lt;code&gt;a&lt;/code&gt; to the output of type &lt;code&gt;c&lt;/code&gt;), but if the answer from the third argument is of type &lt;code&gt;&lt;tt&gt;Right&lt;/tt&gt; b&lt;/code&gt;, then feed &lt;code&gt;b&lt;/code&gt; to the second argument (a function that converts the input value of type &lt;code&gt;b&lt;/code&gt; to the output of type &lt;code&gt;c&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;What we've seen in this entry is an introduction to the &lt;tt&gt;MonadPlus&lt;/tt&gt; class and three examples of monads that allow for choice, &lt;tt&gt;Maybe&lt;/tt&gt;, the list data type and &lt;tt&gt;Either&lt;/tt&gt;, and saw an example for each which demonstrated their ability to code with choice.&lt;br /&gt;&lt;br /&gt;The &lt;a href='http://logicaltypes.blogspot.com/2008/05/guarded-choice-with-monadplus.html'&gt;next entry&lt;/a&gt; will further explore the &lt;code&gt;&lt;font color='blue'&gt;MonadPlus&lt;/font&gt;&lt;/code&gt; class and some of its powerful functions, such as &lt;code&gt;msum&lt;/code&gt; and &lt;kbd&gt;guard&lt;/kbd&gt;, and how the &lt;tt&gt;MonadPlus&lt;/tt&gt; class allows us to code in a declarative nondeterministic style.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-4297965994465507927?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/4297965994465507927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=4297965994465507927' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4297965994465507927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4297965994465507927'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/choice-with-monads-list-maybe-either.html' title='Choice with Monads: List, Maybe, Either'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-4536597662845799183</id><published>2008-05-14T15:28:00.000-07:00</published><updated>2008-08-02T18:59:38.686-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='maybe'/><category scheme='http://www.blogger.com/atom/ns#' term='memoization'/><title type='text'>No "fib"bing; getting into the monad groove</title><content type='html'>The title is groan-inducing, as all my "jokes" are.  I guarantee it: once you've finished reading this entry, reread the title, and you won't be able to stop from groaning.&lt;br /&gt;&lt;br /&gt;The &lt;a href='http://en.wikipedia.org/wiki/Fibonacci_number'&gt;Fibonacci series&lt;/a&gt; goes as follows:  0,1,1,2,3,5,8,13..., or put another way, the current number is obtained by adding the previous two numbers.  It is useful for many things, as its limit is the golden ratio, found in nature (the spiral of some &lt;a href='http://en.wikipedia.org/wiki/Crustacean'&gt;crustaceans&lt;/a&gt; and the population growth of &lt;a href='http://www.youtube.com/watch?v=BHiJK1KJHac&amp;feature=related'&gt;rabbits&lt;/a&gt; &lt;em&gt;[they &lt;u&gt;must&lt;/u&gt; be stopped!]&lt;/em&gt;) and in artifice (windows, painting, doors, buildings follow the width and height of this ratio)).&lt;br /&gt;&lt;br /&gt;Any fibonacci number can be easily computed from the following formula ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;fib :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt;&lt;br /&gt;fib n | n &amp;equiv; 0     = 0&lt;br /&gt;      | n &amp;equiv; 1     = 1&lt;br /&gt;      | &lt;kbd&gt;otherwise&lt;/kbd&gt; = fib (n-1) + fib (n-2)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... that is, easily computed if this world were purely mathematical, including the &lt;em&gt;caveat&lt;/em&gt; that any computable function could be instantly computed.  Run on a computer, &lt;code&gt;fib 25&lt;/code&gt; slows noticeably and &lt;code&gt;fib 50&lt;/code&gt; may as well describe the &lt;a href='http://en.wikipedia.org/wiki/Halting_problem'&gt;halting problem&lt;/a&gt;, because I wasn't going to wait around for it to terminate.&lt;br /&gt;&lt;br /&gt;Note the similarity between the computation of the Fibonacci series to the computation of the &lt;a href='http://logicaltypes.blogspot.com/2008/05/oh-my-acking-monad.html'&gt;Ackermann table&lt;/a&gt;.  They are not the same kind of problem, mind you, as the Ackermann is not primitively recursive; the Fibonacci is "only" doubly (branching) recursive.  But they are similar enough in that they can be solved in similar ways.  Given that the current Fibonacci number is the sum of the previous two Fibonacci numbers, we need only a (reversed) list to &lt;em&gt;memoize&lt;/em&gt; the previous results, so the above sequence becomes:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;[..., 13, 8, 5, 3, 2, 1, 1, 0]&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;and the "next" Fibonacci number would be simply the first two elements of this list (21, in this case).  But how do we know where we are in the sequence?  Easy: the length of this list tells us where we are, and in this case, the list has 8 elements, meaning the "next" Fib is 9th in the sequence.&lt;br /&gt;&lt;br /&gt;So, turning to monads with this list structure for memoization, the code falls out as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;fib :: &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;FibS&lt;/tt&gt;&lt;br /&gt;fib n = get &gt;&gt;= &amp;lambda;mem . &lt;kbd&gt;maybe&lt;/kbd&gt; (fib' n &gt;&gt;= update)&lt;br /&gt;                             &lt;kbd&gt;return&lt;/kbd&gt;&lt;br /&gt;                             (gimme mem n)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, &lt;code&gt;fib&lt;/code&gt; is now simply a decision: "Do I have the fib requested in the list?" "Yes: &lt;code&gt;gimme&lt;/code&gt; it and &lt;kbd&gt;return&lt;/kbd&gt; it" or "No: compute it and then &lt;code&gt;update&lt;/code&gt; the list"&lt;br /&gt;&lt;br /&gt;The list is a very slight variation on a regular list type, as we choose to carry around its length (as opposed to recomputing it at each iteration), and we lift this new data type into the &lt;tt&gt;State&lt;/tt&gt; monad (as we did with the &lt;tt&gt;Map&lt;/tt&gt; data type for our Ackermann monad optimization):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;data&lt;/kbd&gt; &lt;tt&gt;Mem&lt;/tt&gt; = &lt;tt&gt;Mem&lt;/tt&gt; [&lt;tt&gt;Integer&lt;/tt&gt;] &lt;tt&gt;Int&lt;/tt&gt;&lt;br /&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;FibS&lt;/tt&gt; = &lt;tt&gt;State Mem Integer&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;The actual computation function is lifted into the monadic form with very little variation ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;fib' :: &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;FibS&lt;/tt&gt;&lt;br /&gt;fib' n | n &amp;equiv; 0     = &lt;kbd&gt;return&lt;/kbd&gt; 0&lt;br /&gt;       | n &amp;equiv; 1     = &lt;kbd&gt;return&lt;/kbd&gt; 1&lt;br /&gt;       | &lt;kbd&gt;otherwise&lt;/kbd&gt; = liftM2 (+) (fib (n - 1)) (fib (n - 2))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... where monadic addition, &lt;code&gt;liftM2 (+)&lt;/code&gt;, replaces addition in the usual sense (recall the &lt;a href='http://logicaltypes.blogspot.com/2008/05/trivial-monad-solutions.html'&gt;spot of bother&lt;/a&gt; we had "adding" Thing One to Thing Two), and where the plain numbers are lifted into the monad with &lt;kbd&gt;return&lt;/kbd&gt;.  In brief, the substance is now monadic but the structure is the same as our original, plain, &lt;code&gt;fib&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;The other housekeeping functions are new for the monadic solution, but what one would expect.  The &lt;code&gt;update&lt;/code&gt; follows in the same vein as the one for the &lt;a href='http://dauclair.blogspot.com/2008/04/oh-my-acking-monad.html'&gt;ackermann monad&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;update :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;FibS&lt;/tt&gt;&lt;br /&gt;update n = &lt;kbd&gt;do&lt;/kbd&gt; (&lt;tt&gt;Mem&lt;/tt&gt; lst len) &amp;larr; get&lt;br /&gt;              put (&lt;tt&gt;Mem&lt;/tt&gt; (n:lst) (len + 1))&lt;br /&gt;              &lt;kbd&gt;return&lt;/kbd&gt; n&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;An interpretation of the &lt;code&gt;update&lt;/code&gt; function is that it is the identity function with the side-effect that it remembers the result that it &lt;kbd&gt;return&lt;/kbd&gt;s.&lt;br /&gt;&lt;br /&gt;The only other function is the self-describing &lt;code&gt;gimme&lt;/code&gt; which retrieves a previously-computed fibonacci number from memory:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;gimme :: &lt;tt&gt;Mem&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Int&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Maybe Integer&lt;/tt&gt;&lt;br /&gt;gimme (&lt;tt&gt;Mem&lt;/tt&gt; (h:t) len) n | len &amp;equiv; n   = &lt;tt&gt;Just&lt;/tt&gt; h&lt;br /&gt;                        | len &gt; n   = &lt;kbd&gt;let&lt;/kbd&gt; x = (len - 1) - n&lt;br /&gt;                                      &lt;kbd&gt;in&lt;/kbd&gt; &lt;tt&gt;Just&lt;/tt&gt; (t !! x)&lt;br /&gt;                        | &lt;kbd&gt;otherwise&lt;/kbd&gt; = &lt;tt&gt;Nothing&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;This &lt;code&gt;gimme&lt;/code&gt; function uses the &lt;a href='http://haskell.org/onlinereport/maybe.html'&gt;&lt;tt&gt;Maybe&lt;/tt&gt; monad&lt;/a&gt; and &lt;a href='http://en.wikibooks.org/wiki/Haskell/Advanced_monads'&gt;its functionality&lt;/a&gt;, saying "If I have the value already computed &lt;em&gt;[If the list length is equal to or greater than the requested index]&lt;/em&gt;, then return &lt;tt&gt;Just&lt;/tt&gt; that value; &lt;kbd&gt;otherwise&lt;/kbd&gt; I've got &lt;tt&gt;Nothing&lt;/tt&gt;, so you need to compute that value."&lt;br /&gt;&lt;br /&gt;In summary, we've decorated the na&amp;iuml;ve fibonacci algorithm with some memory and three new functions (one manager and two support functions).  What is the payoff?&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;font color='black'&gt;Ready&gt;&lt;/font&gt; fib 1500&lt;br /&gt;&lt;em&gt;[no delay]&lt;/em&gt;&lt;br /&gt;&lt;font color='black'&gt;135511256685631019516369368671484083777860107124184972421335&lt;br /&gt;431532214873108735287506122593540357172653003737788143473202&lt;br /&gt;576992570823565500453499141029242495959974839822286992875272&lt;br /&gt;419318113250950996424476212422002092544399201969604653214384&lt;br /&gt;983053458933789325853933815390935494792961948008381459961871&lt;br /&gt;22583354898000&lt;br /&gt;&lt;br /&gt;Ready&gt;&lt;/font&gt; fib 50000&lt;br /&gt;&lt;em&gt;[4 second delay]&lt;/em&gt;&lt;br /&gt;&lt;em&gt;[&lt;a href='http://www.cotilliongroup.com/arts/fib50000.txt'&gt;10615 digits&lt;/a&gt;]&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color='black'&gt;Ready&gt;&lt;/font&gt; fib 60000&lt;br /&gt;&lt;em&gt;[2.5 second delay]&lt;/em&gt;&lt;br /&gt;&lt;font color='black'&gt;*** Exception: stack overflow&lt;/font&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;These results are a great step forward over the na&amp;iuml;ve &lt;code&gt;fib&lt;/code&gt; implementation (which essentially froze at &lt;code&gt;fib 50&lt;/code&gt;) and even &lt;a href='http://www.cotilliongroup.com/arts/DCG.html'&gt;memoized implementation reported elsewhere&lt;/a&gt; (which ran out of memory after &lt;code&gt;fib 1450&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Huzzah! then for efficient program representation in Haskell and monadic code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-4536597662845799183?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/4536597662845799183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=4536597662845799183' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4536597662845799183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/4536597662845799183'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/no-fibbing-getting-into-monad-groove.html' title='No &quot;fib&quot;bing; getting into the monad groove'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1215792047976596289</id><published>2008-05-14T15:24:00.000-07:00</published><updated>2008-08-02T19:09:36.055-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='memoization'/><title type='text'>Oh! my acking monad!</title><content type='html'>So, we just saw, after &lt;a href='http://logicaltypes.blogspot.com/2008/05/trivial-monad-solutions-cont.html'&gt;reams of paper on proving in inscrutable detail the three monadic laws&lt;/a&gt;, that after all that, we see that &lt;a href='http://logicaltypes.blogspot.com/2008/05/orators-exercise.html'&gt;using them is pretty easy&lt;/a&gt;.  &lt;a href='http://en.wikipedia.org/wiki/Hedda_Gabler'&gt;Fancy that, Hedda!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Haskell does provide several different kinds of monads for various uses, but sometimes one must roll one's own to fit the current need.  I was exploring the &lt;a href='http://en.wikipedia.org/wiki/Ackermann_function'&gt;ackermann function&lt;/a&gt;, curious to know what &lt;a href='http://www.cotilliongroup.com/arts/ack42.txt'&gt;A&lt;sub&gt;&lt;small&gt;4,2&lt;/small&gt;&lt;/sub&gt; looked like&lt;/a&gt; &lt;em&gt;[oh, yes, 19730 digits in all its (gory) glory -- I went there!]&lt;/em&gt; (other than the cop-out of 2&lt;sup&gt;&lt;small&gt;65536&lt;/small&gt;&lt;/sup&gt;-3 that is listed in Wikipedia), and whether my computer could calculate and display that value &lt;em&gt;[obviously it could, but it took some work (see below) to arrive at that point]&lt;/em&gt;.  The ackermann function written in Haskell looks very much like its representation in standard mathematical notation:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;a :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt;&lt;br /&gt;a m n | m &amp;equiv; 0           = n + 1&lt;br /&gt;      | m &gt; 0 &amp;and; n &amp;equiv; 0   = a (m - 1) 1&lt;br /&gt;      | m &gt; 0 &amp;and; n &gt; 0   = a (m - 1) (a m (n - 1))&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The "problem" with the Ackermann function is that even though it is easy to write, the recursion required to arrive at a solution from even small (single digit) inputs is staggering.  My computer staggered and then killed the computation in mid-process (too bad &lt;a href='http://en.wikipedia.org/wiki/Wolf_in_the_Fold_(TOS_episode)'&gt;Redjak didn't have that option&lt;/a&gt;).  The Ackermann function, being not primitively recursive, is also highly redundantly recursive, so it would be nice to provide "hints" to the program, something like: "Oh, you've already computed A&lt;sub&gt;&lt;small&gt;3,1&lt;/small&gt;&lt;/sub&gt; to be 13, so you don't need to recompute that entire branch any more."&lt;br /&gt;&lt;br /&gt;This "hinting" has a name in computer science; it's called "memoization", and Haskell provides the State monad that can be used to cover that functionality quite nicely.  As we're computing the values that build up the solution, we put the smaller-indexed solutions into a dictionary, something like:&lt;table border='0'&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;A&lt;sub&gt;&lt;small&gt;3,1&lt;/small&gt;&lt;/sub&gt;&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;A&lt;sub&gt;&lt;small&gt;2,2&lt;/small&gt;&lt;/sub&gt;&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;7&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;A&lt;sub&gt;&lt;small&gt;2,1&lt;/small&gt;&lt;/sub&gt;&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td colspan='3' align='center'&gt;... and so forth ...&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Such a dictionary in Haskell is called a &lt;tt&gt;Map&lt;/tt&gt;, because we are mapping from the "word" (the indices of the Ackermann function) to the "definition" (the solution)...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;Index&lt;/tt&gt; = (&lt;tt&gt;Integer&lt;/tt&gt;, &lt;tt&gt;Integer&lt;/tt&gt;)&lt;br /&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;AckMap&lt;/tt&gt; = &lt;tt&gt;Map Index Integer&lt;/tt&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... and we wrap that &lt;tt&gt;Map&lt;/tt&gt; with the &lt;tt&gt;State&lt;/tt&gt; monad ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;kbd&gt;type&lt;/kbd&gt; &lt;tt&gt;AckMapS&lt;/tt&gt; = &lt;tt&gt;State AckMap Integer&lt;/tt&gt;&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... where &lt;tt&gt;AckMapS&lt;/tt&gt; uses the &lt;tt&gt;AckMap&lt;/tt&gt; dictionary to provide the preexisting (partial) solution, or, given there's none yet, populates the solution calculated (the &lt;tt&gt;Integer&lt;/tt&gt;) into the dictionary at the current &lt;tt&gt;Index&lt;/tt&gt;.  Simple, yes?  So, all we need is an utility function that does the lookup or updates the state ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;ackify :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;AckMapS&lt;/tt&gt;&lt;br /&gt;ackify m n = get &gt;&gt;= &amp;lambda;ma . &lt;kbd&gt;maybe&lt;/kbd&gt; (a' m n &gt;&gt;= update m n) &lt;br /&gt;                                 &lt;kbd&gt;return&lt;/kbd&gt;&lt;br /&gt;                                 (&lt;tt&gt;Map&lt;/tt&gt;.&lt;kbd&gt;lookup&lt;/kbd&gt; (m, n) ma)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... the update function that actually does the housekeeping ...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;update :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;AckMapS&lt;/tt&gt;&lt;br /&gt;update m n ans = &lt;kbd&gt;do&lt;/kbd&gt; mappo &amp;larr; get&lt;br /&gt;                    put (&lt;tt&gt;Map&lt;/tt&gt;.insert (m, n) ans mappo)&lt;br /&gt;                    &lt;kbd&gt;return&lt;/kbd&gt; ans&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... so that our monadic version of the ackermann function is as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;a' :: &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;Integer&lt;/tt&gt; &amp;rarr; &lt;tt&gt;AckMapS&lt;/tt&gt;&lt;br /&gt;a' m n | m &amp;equiv; 0           = &lt;kbd&gt;return&lt;/kbd&gt; (n + 1)&lt;br /&gt;       | m &gt; 0 &amp;and; n &amp;equiv; 0   = ackify (m - 1) 1&lt;br /&gt;       | m &gt; 0 &amp;and; n &gt; 0   = ackify m (n - 1) &gt;&gt;= ackify (m - 1)&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;which looks very much the same as the original function, with calls to &lt;code&gt;a&lt;/code&gt; being replaced by calls to the lookup-or-update &lt;code&gt;ackify&lt;/code&gt; function and function composition (e.g. &lt;code&gt;a (m - 1) (a m (n - 1))&lt;/code&gt;) being replaced by the monadic composer, &lt;code&gt;&gt;&gt;=&lt;/code&gt;.  So, from the above demonstration we see that monads are not only easy to use, but also easy to "roll your own" and integrate into preexisting non-monadic code without much fuss.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Critique&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Although the incorporation of the &lt;tt&gt;State&lt;/tt&gt; monad dramatically speeds processing solutions and makes some solutions computable that were unreachable under the na&amp;iuml;ve approach, there are at least two better generalizations:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Use the fixpoint (or the &lt;a href='http://en.wikipedia.org/wiki/Fixed_point_combinator'&gt;Y-combinator&lt;/a&gt;) of the ackermann function so that one can now &lt;a href='http://groups.google.bs/group/comp.lang.haskell/browse_thread/thread/89703a5aad523dc5'&gt;decorate the engine of computation without altering its structure at all&lt;/a&gt;!  Incredible!  So instead of using a monad to abstract stateful decoration of computations, the fixpont can be used to abstract &lt;em&gt;any&lt;/em&gt; decoration of computation!&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use the compiler to change the code, instead of having it programmed in.  Many functional language compilers have the option to memoize computations automagically.   So, instead of writing code that memorizes partial results, the compiler intercepts the computation, replacing computation with previously calculated values (or running the computation if no such value exists and then storing &lt;em&gt;that&lt;/em&gt; result into the runtime). No extra coding; no "troublesome" monads.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Critique on the critique&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;On the other hand (&lt;em&gt;"there are five fingers"&lt;/em&gt;, as my favorite Mother-in-law enjoys rejoining),&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;The fixpoint solution is more general and more elegant, but being more general suffers in a slight decrease in efficiency:  it more than likely will run more slowly than the specialized monadic state solution&lt;/li&gt;&lt;br /&gt;&lt;li&gt;With an explicit encoding of state, the programmer has direct say into what is memoized and what is not, but with a compiler directive, &lt;em&gt;everything&lt;/em&gt; is memoized.  Since the Ackermann function can be represented by simple functions for m &amp;lt; 4, the map can be replaced by a faux-map for those values, reducing the memory footprint of memoization to only a couple of cells for m == 4 (as opposed to over 150,000 cells for m == 4 and n == 1 using the na&amp;iuml;ve memoization scheme).&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;... so the above described solution may be "good enough" for the task at hand, after all.  Put another way, when I said I was wrong, I might have been wrong.  &lt;em&gt;Caveat programmer.&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4650294074444534066-1215792047976596289?l=logicaltypes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://logicaltypes.blogspot.com/feeds/1215792047976596289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4650294074444534066&amp;postID=1215792047976596289' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1215792047976596289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4650294074444534066/posts/default/1215792047976596289'/><link rel='alternate' type='text/html' href='http://logicaltypes.blogspot.com/2008/05/oh-my-acking-monad.html' title='Oh! my acking monad!'/><author><name>geophf</name><uri>http://www.blogger.com/profile/09936874508556500234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_D0Q0X4rkBtw/SKx85KGcnCI/AAAAAAAAABM/78ni0P7qt-Y/S220/fear.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4650294074444534066.post-1532766924064112371</id><published>2008-05-14T15:17:00.000-07:00</published><updated>2008-08-02T19:16:50.566-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monad'/><category scheme='http://www.blogger.com/atom/ns#' term='poem'/><title type='text'>Orators' exercise</title><content type='html'>I practice &lt;a href='http://www.cotilliongroup.com/arts/en-verse.html'&gt;this exercise&lt;/a&gt; daily.  Don't sight read it; read it aloud.  The &lt;a href='http://haskell.org'&gt;Haskell&lt;/a&gt; program that produced this uses a &lt;a href='http://logicaltypes.blogspot.com/2008/05/trivial-monad-solutions.html'&gt;monad&lt;/a&gt;; the heart of which is as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;-- parses a poem, refering words to CMU for pronounciation&lt;br /&gt;&lt;br /&gt;parsePoem = &lt;kbd&gt;do&lt;/kbd&gt; p &amp;larr; &lt;kbd&gt;getContents&lt;/kbd&gt;&lt;br /&gt;               &lt;kbd&gt;return&lt;/kbd&gt; (checkEachLine (&lt;kbd&gt;lines&lt;/kbd&gt; p))&lt;br /&gt;&lt;br /&gt;main = &lt;kbd&gt;do&lt;/kbd&gt; p &amp;larr; parsePoem&lt;br /&gt;          &lt;kbd&gt;putStr&lt;/kbd&gt; p&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Do you see the monad?  Well, that's a rather mean question, because the monad is entirely implied in this program fragment.  &lt;br /&gt;&lt;br /&gt;One of the motivators for incorporating monads into Haskell was dealing with things in the "real world" that fall outside easy descriptions in purely functional (mathematical) domains.  One of those things is input and output.  Whereas an equation...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;1+1=2&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;... was true yesterday, is true now, and will be true tomorrow (albeit, it took over 100 pages of introduction to set theory in the &lt;em&gt;Principia Mathematica&lt;/em&gt; to be able to back up that truth), things of the "real world", particularly input and output change, and change irrevocably.  For example, if I buy and eat some ice cream &lt;em&gt;(mint chocolate chip, please!)&lt;/em&gt;, I'm not getting a refund.  The state of the world has changed: I'm parted from my money, and that scoop of ice cream is no longer in the shop's inventory (and they have a &lt;a href='http://www.irs.gov'&gt;Form 1120S, Schedule A&lt;/a&gt; to prove it).  Input/output, as part of the state of the world, is one of the members of the &lt;a href='http://research.microsoft.com/~simonpj/papers/marktoberdorf/'&gt;awkward squad&lt;/a&gt;.  So, to help it to be a used and useful language, the Haskell designers included the &lt;tt&gt;IO&lt;/tt&gt; monad as one of the libraries.&lt;br /&gt;&lt;br /&gt;So, if one were to query &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;parsePoem&lt;/code&gt;, one would find that they are the types &lt;tt&gt;IO&lt;/tt&gt; &lt;code&gt;()&lt;/code&gt; and  &lt;code&gt;&lt;tt&gt;IO&lt;/tt&gt; [&lt;tt&gt;Char&lt;/tt&gt;]&lt;/code&gt;, respectively, meaning that &lt;code&gt;main&lt;/code&gt; interacts with &lt;tt&gt;IO&lt;/tt&gt;, returning "nothing", and &lt;code&gt;parsePoem&lt;/code&gt; interacts with &lt;tt&gt;IO&lt;/tt&gt;, returning a list of characters (the &lt;a href='http://www.cotilliongroup.com/arts/en-verse.html'&gt;poem&lt;/a&gt; that you just finished reading aloud).&lt;br /&gt;&lt;br /&gt;In short, the &lt;tt&gt;IO&lt;/tt&gt; monad does all the handshaking (or, more correctly, hand&lt;em&gt;waving&lt;/em&gt;) with the state of the world, so the programmer can do something as "simple" as printing "Hello, world!" easily.  All this monad asks, as every monad asks, is &lt;a href='http://www.imdb.com/title/tt0032138/'&gt;"Pay no attention to that man behind the curtain."&lt;/a&gt;&lt;div class="blogger-post-footer"
